Long-press a notification to find out who sent it.
Bug: 5547401 Change-Id: I8d5d73723b3f03f5b0f8717faaca826b1530df7a
This commit is contained in:
22
packages/SystemUI/res/menu/notification_popup_menu.xml
Normal file
22
packages/SystemUI/res/menu/notification_popup_menu.xml
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user