diff options
author | Dan Sandler <dsandler@android.com> | 2014-07-25 19:30:44 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-07-25 19:30:44 +0000 |
commit | 7ae09aebe2b1c2230cc67f8991118a782ff1e202 (patch) | |
tree | 9ec1809ffb56a42e7a204a088f14b8c765478ec8 | |
parent | 58385d11cddbdb2f8bb0f81f953549b84fe1caf4 (diff) | |
parent | 99137c5e8d92ba02ee1a06ae867a08ff328920af (diff) | |
download | frameworks_base-7ae09aebe2b1c2230cc67f8991118a782ff1e202.zip frameworks_base-7ae09aebe2b1c2230cc67f8991118a782ff1e202.tar.gz frameworks_base-7ae09aebe2b1c2230cc67f8991118a782ff1e202.tar.bz2 |
am c9d55d0c: Merge "Notification inspector." into lmp-dev
* commit 'c9d55d0cc1aca2840626754c89a30e27c30b1764':
Notification inspector.
8 files changed, 300 insertions, 69 deletions
diff --git a/packages/SystemUI/res/drawable/notification_guts_bg.xml b/packages/SystemUI/res/drawable/notification_guts_bg.xml new file mode 100644 index 0000000..07932d1 --- /dev/null +++ b/packages/SystemUI/res/drawable/notification_guts_bg.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@color/notification_guts_bg_color" /> + <corners android:radius="@dimen/notification_material_rounded_rect_radius" /> +</shape> diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml new file mode 100644 index 0000000..0e78d66 --- /dev/null +++ b/packages/SystemUI/res/layout/notification_guts.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2014, 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. +--> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/notification_guts_bg" + android:id="@+id/notification_guts" + android:visibility="gone" + android:clickable="true" + android:gravity="top|start" + > + <LinearLayout + android:layout_width="match_parent" + android:layout_height="@android:dimen/notification_large_icon_height" + android:orientation="horizontal" + > + + <ImageView android:id="@android:id/icon" + android:layout_width="@android:dimen/notification_large_icon_width" + android:layout_height="@android:dimen/notification_large_icon_height" + android:layout_weight="0" + android:padding="8dp" + android:scaleType="centerInside" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="start|center_vertical" + android:orientation="vertical" + android:paddingStart="8dp" + android:paddingEnd="8dp" + android:layout_weight="1" + > + <TextView + android:id="@+id/pkgname" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|start" + android:layout_weight="1" + android:textAppearance="@*android:style/TextAppearance.StatusBar.Material.EventContent.Title" + android:textColor="@color/notification_guts_title_color" + /> + <DateTimeView + android:id="@+id/timestamp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:layout_gravity="center_vertical|start" + android:textAppearance="@*android:style/TextAppearance.StatusBar.Material.EventContent.Time" + android:textColor="@color/notification_guts_text_color" + /> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/debug_info" + android:layout_weight="0" + android:textAppearance="@*android:style/TextAppearance.StatusBar.Material.EventContent.Time" + android:layout_gravity="bottom|start" + android:visibility="gone" + android:textColor="@color/notification_guts_text_color" + /> + </LinearLayout> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="8dp" + android:layout_weight="0" + android:orientation="horizontal" + android:showDividers="beginning|middle" + android:divider="@*android:drawable/list_divider_holo_dark" + android:dividerPadding="8dp" + > + <Button style="@android:style/Widget.Material.Light.Button.Borderless.Small" + android:id="@+id/notification_inspect_item" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="start|center_vertical" + android:drawablePadding="8dp" + android:paddingStart="8dp" + android:textColor="@color/notification_guts_btn_color" + android:textSize="14dp" + android:singleLine="true" + android:ellipsize="end" + android:text="@string/status_bar_notification_inspect_item_title" + /> + </LinearLayout> + </LinearLayout> +</FrameLayout> diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml index 7663d54..ef4e27c 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_row.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml @@ -1,3 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2014, 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. +--> + <com.android.systemui.statusbar.ExpandableNotificationRow xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" @@ -35,17 +52,11 @@ android:paddingStart="8dp" /> - <TextView - android:id="@+id/debug_info" - android:visibility="invisible" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="bottom|end" - android:fontFamily="sans-serif-condensed" - android:textSize="9dp" - android:textStyle="bold" - android:textColor="#00A040" - android:padding="2dp" + <include + layout="@layout/notification_guts" + android:id="@+id/notification_guts" + android:layout_width="match_parent" + android:layout_height="match_parent" /> <com.android.systemui.statusbar.NotificationScrimView diff --git a/packages/SystemUI/res/menu/notification_popup_menu.xml b/packages/SystemUI/res/menu/notification_popup_menu.xml deleted file mode 100644 index 8923fb6..0000000 --- a/packages/SystemUI/res/menu/notification_popup_menu.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?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> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 5ecba32..a718f4f 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -94,4 +94,10 @@ <color name="current_user_border_color">@color/system_accent_color</color> <color name="segmented_button_text_inactive">#99afbdc4</color><!-- 60% --> + + <!-- The "inside" of a notification, reached via longpress --> + <color name="notification_guts_bg_color">#ff424242</color><!-- grey 800 --> + <color name="notification_guts_title_color">#FFFFFFFF</color> + <color name="notification_guts_text_color">#99FFFFFF</color> + <color name="notification_guts_btn_color">#FFFFFFFF</color> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 6e1ba3c..6c30c89 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -76,10 +76,12 @@ public class SwipeHelper implements Gefingerpoken { private float mDensityScale; private boolean mLongPressSent; - private View.OnLongClickListener mLongPressListener; + private LongPressListener mLongPressListener; private Runnable mWatchLongPress; private long mLongPressTimeout; + final private int[] mTmpPos = new int[2]; + public SwipeHelper(int swipeDirection, Callback callback, Context context) { mCallback = callback; mHandler = new Handler(); @@ -93,7 +95,7 @@ public class SwipeHelper implements Gefingerpoken { android.R.interpolator.fast_out_linear_in); } - public void setLongPressListener(View.OnLongClickListener listener) { + public void setLongPressListener(LongPressListener listener) { mLongPressListener = listener; } @@ -215,7 +217,7 @@ public class SwipeHelper implements Gefingerpoken { } } - public boolean onInterceptTouchEvent(MotionEvent ev) { + public boolean onInterceptTouchEvent(final MotionEvent ev) { final int action = ev.getAction(); switch (action) { @@ -237,8 +239,12 @@ public class SwipeHelper implements Gefingerpoken { public void run() { if (mCurrView != null && !mLongPressSent) { mLongPressSent = true; - mCurrView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); - mLongPressListener.onLongClick(mCurrView); + mCurrView.sendAccessibilityEvent( + AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); + mCurrView.getLocationOnScreen(mTmpPos); + final int x = (int) ev.getRawX() - mTmpPos[0]; + final int y = (int) ev.getRawY() - mTmpPos[1]; + mLongPressListener.onLongPress(mCurrView, x, y); } } }; @@ -267,14 +273,16 @@ public class SwipeHelper implements Gefingerpoken { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: + final boolean captured = (mDragging || mLongPressSent); mDragging = false; mCurrView = null; mCurrAnimView = null; mLongPressSent = false; removeLongPressCallback(); + if (captured) return true; break; } - return mDragging; + return mDragging || mLongPressSent; } /** @@ -460,4 +468,15 @@ public class SwipeHelper implements Gefingerpoken { */ boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress); } + + /** + * Equivalent to View.OnLongClickListener with coordinates + */ + public interface LongPressListener { + /** + * Equivalent to {@link View.OnLongClickListener#onLongClick(View)} with coordinates + * @return whether the longpress was handled + */ + boolean onLongPress(View v, int x, int y); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index a2595bf..48fc4ec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -16,6 +16,9 @@ package com.android.systemui.statusbar; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.TimeInterpolator; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.Notification; @@ -33,6 +36,7 @@ import android.content.pm.UserInfo; import android.content.res.Configuration; import android.database.ContentObserver; import android.graphics.Rect; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; @@ -57,18 +61,17 @@ import android.util.SparseBooleanArray; 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.ViewAnimationUtils; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; -import android.view.ViewStub; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import android.view.animation.AnimationUtils; import android.widget.DateTimeView; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.PopupMenu; import android.widget.RemoteViews; import android.widget.TextView; @@ -79,6 +82,7 @@ import com.android.internal.util.NotificationColorUtil; import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SearchPanelView; +import com.android.systemui.SwipeHelper; import com.android.systemui.SystemUI; import com.android.systemui.statusbar.NotificationData.Entry; import com.android.systemui.statusbar.phone.KeyguardTouchDelegate; @@ -141,8 +145,6 @@ public abstract class BaseStatusBar extends SystemUI implements // Search panel protected SearchPanelView mSearchPanelView; - protected PopupMenu mNotificationBlamePopup; - protected int mCurrentUserId = 0; final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>(); @@ -184,6 +186,11 @@ public abstract class BaseStatusBar extends SystemUI implements protected int mZenMode; + // which notification is currently being longpress-examined by the user + private View mNotificationGutsExposed; + + private TimeInterpolator mLinearOutSlowIn, mFastOutLinearIn; + /** * The {@link StatusBarState} of the status bar. */ @@ -416,6 +423,11 @@ public abstract class BaseStatusBar extends SystemUI implements mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.linear_out_slow_in); + mFastOutLinearIn = AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.fast_out_linear_in); + // Connect in to the status bar manager service StatusBarIconList iconList = new StatusBarIconList(); mCommandQueue = new CommandQueue(this, iconList); @@ -593,29 +605,61 @@ public abstract class BaseStatusBar extends SystemUI implements null, UserHandle.CURRENT); } - protected View.OnLongClickListener getNotificationLongClicker() { - return new View.OnLongClickListener() { + private static final int max(int...args) { + switch (args.length) { + case 0: + return 0; + case 1: + return args[0]; + case 2: + return args[1] > args[0] ? args[1] : args[0]; + default: + int m = args[0]; + for (int i = 0; i < args.length; i++) { + if (args[i] > m) { + m = args[i]; + } + } + return m; + } + } + + protected SwipeHelper.LongPressListener getNotificationLongClicker() { + return new SwipeHelper.LongPressListener() { @Override - public boolean onLongClick(View v) { + public boolean onLongPress(View v, int x, int y) { + dismissPopups(); + final String packageNameF = (String) v.getTag(); if (packageNameF == null) return false; if (v.getWindowToken() == null) return false; - mNotificationBlamePopup = new PopupMenu(mContext, v); - mNotificationBlamePopup.getMenuInflater().inflate( - R.menu.notification_popup_menu, - mNotificationBlamePopup.getMenu()); - mNotificationBlamePopup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - if (item.getItemId() == R.id.notification_inspect_item) { - startApplicationDetailsActivity(packageNameF); - animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); - } else { - return false; - } - return true; + + // Assume we are a status_bar_notification_row + final View guts = v.findViewById(R.id.notification_guts); + if (guts == null) return false; + + // Already showing? + if (guts.getVisibility() == View.VISIBLE) return false; + + final View button = guts.findViewById(R.id.notification_inspect_item); + button.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + startApplicationDetailsActivity(packageNameF); + animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); } }); - mNotificationBlamePopup.show(); + + guts.setVisibility(View.VISIBLE); + final double horz = Math.max(v.getWidth() - x, x); + final double vert = Math.max(v.getHeight() - y, y); + final float r = (float) Math.hypot(horz, vert); + final Animator a + = ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r); + a.setDuration(400); + a.setInterpolator(mLinearOutSlowIn); + a.start(); + + mNotificationGutsExposed = guts; return true; } @@ -623,9 +667,24 @@ public abstract class BaseStatusBar extends SystemUI implements } public void dismissPopups() { - if (mNotificationBlamePopup != null) { - mNotificationBlamePopup.dismiss(); - mNotificationBlamePopup = null; + if (mNotificationGutsExposed != null) { + final View v = mNotificationGutsExposed; + mNotificationGutsExposed = null; + + final int x = (v.getLeft() + v.getRight()) / 2; + final int y = (v.getTop() + v.getBottom()) / 2; + final Animator a = ViewAnimationUtils.createCircularReveal(v, + x, y, x, 0); + a.setDuration(200); + a.setInterpolator(mFastOutLinearIn); + a.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + v.setVisibility(View.GONE); + } + }); + a.start(); } } @@ -910,6 +969,27 @@ public abstract class BaseStatusBar extends SystemUI implements return inflateViews(entry, parent, true); } + private Drawable loadPackageIconDrawable(String pkg, int userId) { + Drawable icon = null; + try { + icon = mContext.getPackageManager().getApplicationIcon(pkg); + } catch (PackageManager.NameNotFoundException e) { + } + + return icon; + } + + private CharSequence loadPackageName(String pkg) { + final PackageManager pm = mContext.getPackageManager(); + try { + ApplicationInfo info = pm.getApplicationInfo(pkg, + PackageManager.GET_UNINSTALLED_PACKAGES); + if (info != null) return pm.getApplicationLabel(info); + } catch (PackageManager.NameNotFoundException e) { + } + return pkg; + } + private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent, boolean isHeadsUp) { int maxHeight = mRowMaxHeight; StatusBarNotification sbn = entry.notification; @@ -957,8 +1037,15 @@ public abstract class BaseStatusBar extends SystemUI implements parent, false); } - // for blaming (see SwipeHelper.setLongPressListener) + // the notification inspector (see SwipeHelper.setLongPressListener) row.setTag(sbn.getPackageName()); + final View guts = row.findViewById(R.id.notification_guts); + final Drawable pkgicon = loadPackageIconDrawable(entry.notification.getPackageName(), + entry.notification.getUserId()); + final String pkgname = loadPackageName(entry.notification.getPackageName()).toString(); + ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon); + ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(entry.notification.getPostTime()); + ((TextView) row.findViewById(R.id.pkgname)).setText(pkgname); workAroundBadLayerDrawableOpacity(row); View vetoButton = updateNotificationVetoButton(row, sbn); @@ -1202,6 +1289,9 @@ public abstract class BaseStatusBar extends SystemUI implements protected void visibilityChanged(boolean visible) { if (mPanelSlightlyVisible != visible) { mPanelSlightlyVisible = visible; + if (!visible) { + dismissPopups(); + } try { if (visible) { mBarService.onPanelRevealed(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 079cb88..8b4e79f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -164,7 +164,7 @@ public class NotificationStackScrollLayout extends ViewGroup * motion. */ private int mMaxScrollAfterExpand; - private OnLongClickListener mLongClickListener; + private SwipeHelper.LongPressListener mLongPressListener; /** * Should in this touch motion only be scrolling allowed? It's true when the scroller was @@ -243,7 +243,7 @@ public class NotificationStackScrollLayout extends ViewGroup float densityScale = getResources().getDisplayMetrics().density; float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop(); mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, getContext()); - mSwipeHelper.setLongPressListener(mLongClickListener); + mSwipeHelper.setLongPressListener(mLongPressListener); mSidePaddings = context.getResources() .getDimensionPixelSize(R.dimen.notification_side_padding); @@ -471,9 +471,9 @@ public class NotificationStackScrollLayout extends ViewGroup return mBottomStackPeekSize; } - public void setLongPressListener(View.OnLongClickListener listener) { + public void setLongPressListener(SwipeHelper.LongPressListener listener) { mSwipeHelper.setLongPressListener(listener); - mLongClickListener = listener; + mLongPressListener = listener; } public void setScrollView(ViewGroup scrollView) { |