Long-press a notification to find out who sent it.

Bug: 5547401
Change-Id: I8d5d73723b3f03f5b0f8717faaca826b1530df7a
This commit is contained in:
Daniel Sandler
2012-04-04 14:04:21 -04:00
parent 3dfc82b567
commit f7a1956b06
7 changed files with 123 additions and 3 deletions

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* apps/common/assets/default/default/skins/StatusBar.xml
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/notification_inspect_item" android:title="@string/status_bar_notification_inspect_item_title" />
</menu>

View File

@@ -365,4 +365,8 @@
<!-- Description of the desk dock action that invokes the Android Dreams screen saver feature -->
<string name="dreams_dock_launcher">Activate screen saver</string>
<!-- Title shown in notification popup for inspecting the responsible
application -->
<string name="status_bar_notification_inspect_item_title">App info</string>
</resources>

View File

@@ -23,11 +23,14 @@ import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.graphics.RectF;
import android.os.Handler;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.LinearInterpolator;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
public class SwipeHelper implements Gefingerpoken {
static final String TAG = "com.android.systemui.SwipeHelper";
@@ -57,6 +60,7 @@ public class SwipeHelper implements Gefingerpoken {
private float mPagingTouchSlop;
private Callback mCallback;
private Handler mHandler;
private int mSwipeDirection;
private VelocityTracker mVelocityTracker;
@@ -67,15 +71,24 @@ public class SwipeHelper implements Gefingerpoken {
private boolean mCanCurrViewBeDimissed;
private float mDensityScale;
private boolean mLongPressSent;
private View.OnLongClickListener mLongPressListener;
private Runnable mWatchLongPress;
public SwipeHelper(int swipeDirection, Callback callback, float densityScale,
float pagingTouchSlop) {
mCallback = callback;
mHandler = new Handler();
mSwipeDirection = swipeDirection;
mVelocityTracker = VelocityTracker.obtain();
mDensityScale = densityScale;
mPagingTouchSlop = pagingTouchSlop;
}
public void setLongPressListener(View.OnLongClickListener listener) {
mLongPressListener = listener;
}
public void setDensityScale(float densityScale) {
mDensityScale = densityScale;
}
@@ -167,12 +180,19 @@ public class SwipeHelper implements Gefingerpoken {
}
}
private void removeLongPressCallback() {
if (mWatchLongPress != null) {
mHandler.removeCallbacks(mWatchLongPress);
}
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mDragging = false;
mLongPressSent = false;
mCurrView = mCallback.getChildAtPosition(ev);
mVelocityTracker.clear();
if (mCurrView != null) {
@@ -180,10 +200,28 @@ public class SwipeHelper implements Gefingerpoken {
mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
mVelocityTracker.addMovement(ev);
mInitialTouchPos = getPos(ev);
if (mLongPressListener != null) {
if (mWatchLongPress == null) {
mWatchLongPress = new Runnable() {
@Override
public void run() {
if (mCurrView != null && !mLongPressSent) {
mLongPressSent = true;
mCurrView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
mLongPressListener.onLongClick(mCurrView);
}
}
};
}
mHandler.postDelayed(mWatchLongPress, ViewConfiguration.getLongPressTimeout());
}
}
break;
case MotionEvent.ACTION_MOVE:
if (mCurrView != null) {
if (mCurrView != null && !mLongPressSent) {
mVelocityTracker.addMovement(ev);
float pos = getPos(ev);
float delta = pos - mInitialTouchPos;
@@ -191,14 +229,19 @@ public class SwipeHelper implements Gefingerpoken {
mCallback.onBeginDrag(mCurrView);
mDragging = true;
mInitialTouchPos = getPos(ev) - getTranslation(mCurrAnimView);
removeLongPressCallback();
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mDragging = false;
mCurrView = null;
mCurrAnimView = null;
mLongPressSent = false;
break;
}
return mDragging;
@@ -269,6 +312,10 @@ public class SwipeHelper implements Gefingerpoken {
}
public boolean onTouchEvent(MotionEvent ev) {
if (mLongPressSent) {
return true;
}
if (!mDragging) {
return false;
}

View File

@@ -26,17 +26,20 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
import android.view.Display;
import android.view.IWindowManager;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -45,6 +48,7 @@ import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.PopupMenu;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
@@ -214,6 +218,39 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
private void startApplicationDetailsActivity(String packageName) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
protected View.OnLongClickListener getNotificationLongClicker() {
return new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
final String packageNameF = (String) v.getTag();
if (packageNameF == null) return false;
PopupMenu popup = new PopupMenu(mContext, v);
popup.getMenuInflater().inflate(R.menu.notification_popup_menu, popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.notification_inspect_item) {
startApplicationDetailsActivity(packageNameF);
animateCollapse();
} else {
return false;
}
return true;
}
});
popup.show();
return true;
}
};
}
public void dismissIntruder() {
// pass
}
@@ -355,6 +392,9 @@ public abstract class BaseStatusBar extends SystemUI implements
Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false);
// for blaming (see SwipeHelper.setLongPressListener)
row.setTag(sbn.pkg);
// XXX: temporary: while testing big notifications, auto-expand all of them
ViewGroup.LayoutParams lp = row.getLayoutParams();
if (large != null) {

View File

@@ -314,6 +314,7 @@ public class PhoneStatusBar extends BaseStatusBar {
mExpandedDialog = new ExpandedDialog(context);
mPile = (NotificationRowLayout)expanded.findViewById(R.id.latestItems);
mPile.setLongPressListener(getNotificationLongClicker());
mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
mClearButton = expanded.findViewById(R.id.clear_all_button);

View File

@@ -104,6 +104,10 @@ public class NotificationRowLayout
mExpandHelper = new ExpandHelper(mContext, this, minHeight, maxHeight);
}
public void setLongPressListener(View.OnLongClickListener listener) {
mSwipeHelper.setLongPressListener(listener);
}
public void setAnimateBounds(boolean anim) {
mAnimateBounds = anim;
}

View File

@@ -74,6 +74,7 @@ import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CompatModeButton;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NotificationRowLayout;
import com.android.systemui.statusbar.policy.Prefs;
import java.io.FileDescriptor;
@@ -153,7 +154,7 @@ public class TabletStatusBar extends BaseStatusBar implements
int mNotificationPeekTapDuration;
int mNotificationFlingVelocity;
ViewGroup mPile;
NotificationRowLayout mPile;
BatteryController mBatteryController;
BluetoothController mBluetoothController;
@@ -375,8 +376,9 @@ public class TabletStatusBar extends BaseStatusBar implements
mRecentButton.setOnTouchListener(mRecentsPanel);
mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
mPile = (NotificationRowLayout)mNotificationPanel.findViewById(R.id.content);
mPile.removeAllViews();
mPile.setLongPressListener(getNotificationLongClicker());
ScrollView scroller = (ScrollView)mPile.getParent();
scroller.setFillViewport(true);