diff options
4 files changed, 118 insertions, 72 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java new file mode 100644 index 000000000000..49f1a8d6f248 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2018 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. + */ +package com.android.systemui.statusbar.notification; + +import android.app.Notification; +import android.os.SystemClock; +import android.service.notification.StatusBarNotification; +import android.util.Log; +import android.view.View; + +import com.android.systemui.DejankUtils; +import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; +import com.android.systemui.statusbar.phone.ShadeController; + +/** + * Click handler for generic clicks on notifications. Clicks on specific areas (expansion caret, + * app ops icon, etc) are handled elsewhere. + */ +public final class NotificationClicker implements View.OnClickListener { + private static final String TAG = "NotificationClicker"; + + private final ShadeController mShadeController; + private final BubbleController mBubbleController; + private final NotificationActivityStarter mNotificationActivityStarter; + + public NotificationClicker(ShadeController shadeController, + BubbleController bubbleController, + NotificationActivityStarter notificationActivityStarter) { + mShadeController = shadeController; + mBubbleController = bubbleController; + mNotificationActivityStarter = notificationActivityStarter; + } + + @Override + public void onClick(final View v) { + if (!(v instanceof ExpandableNotificationRow)) { + Log.e(TAG, "NotificationClicker called on a view that is not a notification row."); + return; + } + + mShadeController.wakeUpIfDozing(SystemClock.uptimeMillis(), v); + + final ExpandableNotificationRow row = (ExpandableNotificationRow) v; + final StatusBarNotification sbn = row.getStatusBarNotification(); + if (sbn == null) { + Log.e(TAG, "NotificationClicker called on an unclickable notification,"); + return; + } + + // Check if the notification is displaying the menu, if so slide notification back + if (isMenuVisible(row)) { + row.animateTranslateNotification(0); + return; + } else if (row.isChildInGroup() && isMenuVisible(row.getNotificationParent())) { + row.getNotificationParent().animateTranslateNotification(0); + return; + } else if (row.isSummaryWithChildren() && row.areChildrenExpanded()) { + // We never want to open the app directly if the user clicks in between + // the notifications. + return; + } + + // Mark notification for one frame. + row.setJustClicked(true); + DejankUtils.postAfterTraversal(() -> row.setJustClicked(false)); + + // If it was a bubble we should close it + if (row.getEntry().isBubble()) { + mBubbleController.collapseStack(); + } + + mNotificationActivityStarter.onNotificationClicked(sbn, row); + } + + private boolean isMenuVisible(ExpandableNotificationRow row) { + return row.getProvider() != null && row.getProvider().isMenuVisible(); + } + + /** + * Attaches the click listener to the row if appropriate. + */ + public void register(ExpandableNotificationRow row, StatusBarNotification sbn) { + Notification notification = sbn.getNotification(); + if (notification.contentIntent != null || notification.fullScreenIntent != null) { + row.setOnClickListener(this); + } else { + row.setOnClickListener(null); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index aab3fc4c7a0e..d2a5864f9f33 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -15,6 +15,7 @@ */ package com.android.systemui.statusbar.notification; +import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.systemui.bubbles.BubbleController.DEBUG_DEMOTE_TO_NOTIF; import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY; @@ -36,7 +37,6 @@ import android.os.Handler; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.service.dreams.DreamService; @@ -49,7 +49,6 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; import android.util.Log; -import android.view.View; import android.view.ViewGroup; import com.android.internal.annotations.VisibleForTesting; @@ -57,7 +56,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.util.NotificationMessagingUtil; -import com.android.systemui.DejankUtils; import com.android.systemui.Dependency; import com.android.systemui.Dumpable; import com.android.systemui.EventLogTags; @@ -115,7 +113,6 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. private final NotificationMessagingUtil mMessagingUtil; protected final Context mContext; protected final HashMap<String, NotificationData.Entry> mPendingNotifications = new HashMap<>(); - private final NotificationClicker mNotificationClicker = new NotificationClicker(); private final NotificationGroupManager mGroupManager = Dependency.get(NotificationGroupManager.class); @@ -146,7 +143,6 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. protected IStatusBarService mBarService; private NotificationPresenter mPresenter; private Callback mCallback; - private NotificationActivityStarter mNotificationActivityStarter; protected PowerManager mPowerManager; private NotificationListenerService.RankingMap mLatestRankingMap; protected HeadsUpManager mHeadsUpManager; @@ -161,63 +157,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener; private NotificationViewHierarchyManager.StatusBarStateListener mStatusBarStateListener; @Nullable private AlertTransferListener mAlertTransferListener; - - private final class NotificationClicker implements View.OnClickListener { - - @Override - public void onClick(final View v) { - if (!(v instanceof ExpandableNotificationRow)) { - Log.e(TAG, "NotificationClicker called on a view that is not a notification row."); - return; - } - - getShadeController().wakeUpIfDozing(SystemClock.uptimeMillis(), v); - - final ExpandableNotificationRow row = (ExpandableNotificationRow) v; - final StatusBarNotification sbn = row.getStatusBarNotification(); - if (sbn == null) { - Log.e(TAG, "NotificationClicker called on an unclickable notification,"); - return; - } - - // Check if the notification is displaying the menu, if so slide notification back - if (isMenuVisible(row)) { - row.animateTranslateNotification(0); - return; - } else if (row.isChildInGroup() && isMenuVisible(row.getNotificationParent())) { - row.getNotificationParent().animateTranslateNotification(0); - return; - } else if (row.isSummaryWithChildren() && row.areChildrenExpanded()) { - // We never want to open the app directly if the user clicks in between - // the notifications. - return; - } - - // Mark notification for one frame. - row.setJustClicked(true); - DejankUtils.postAfterTraversal(() -> row.setJustClicked(false)); - - // If it was a bubble we should close it - if (row.getEntry().isBubble()) { - mBubbleController.collapseStack(); - } - - mNotificationActivityStarter.onNotificationClicked(sbn, row); - } - - private boolean isMenuVisible(ExpandableNotificationRow row) { - return row.getProvider() != null && row.getProvider().isMenuVisible(); - } - - public void register(ExpandableNotificationRow row, StatusBarNotification sbn) { - Notification notification = sbn.getNotification(); - if (notification.contentIntent != null || notification.fullScreenIntent != null) { - row.setOnClickListener(this); - } else { - row.setOnClickListener(null); - } - } - } + @Nullable private NotificationClicker mNotificationClicker; private final DeviceProvisionedController.DeviceProvisionedListener mDeviceProvisionedListener = @@ -269,6 +209,10 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. mAlertTransferListener = listener; } + public void setNotificationClicker(NotificationClicker clicker) { + mNotificationClicker = clicker; + } + /** * Our dependencies can have cyclic references, so some need to be lazy */ @@ -355,11 +299,6 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. mOnAppOpsClickListener = mGutsManager::openGuts; } - public void setNotificationActivityStarter( - NotificationActivityStarter notificationActivityStarter) { - mNotificationActivityStarter = notificationActivityStarter; - } - public NotificationData getNotificationData() { return mNotificationData; } @@ -757,7 +696,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. row.setIsLowPriority(isLowPriority); row.setLowPriorityStateUpdated(isUpdate && (wasLowPriority != isLowPriority)); // bind the click event to the content area - mNotificationClicker.register(row, sbn); + checkNotNull(mNotificationClicker).register(row, sbn); // Extract target SDK version. try { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 75e5cbaff936..1e709125c7ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -187,6 +187,7 @@ import com.android.systemui.statusbar.StatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.NotificationActivityStarter; +import com.android.systemui.statusbar.notification.NotificationClicker; import com.android.systemui.statusbar.notification.NotificationData; import com.android.systemui.statusbar.notification.NotificationData.Entry; import com.android.systemui.statusbar.notification.NotificationEntryManager; @@ -630,8 +631,6 @@ public class StatusBar extends SystemUI implements DemoMode, mBubbleController = Dependency.get(BubbleController.class); mBubbleController.setExpandListener(mBubbleExpandListener); - mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager); - mColorExtractor.addOnColorsChangedListener(this); mStatusBarStateController.addCallback(this, StatusBarStateController.RANK_STATUS_BAR); @@ -1018,7 +1017,7 @@ public class StatusBar extends SystemUI implements DemoMode, return new QSFragment(); } - protected void setUpPresenter() { + private void setUpPresenter() { // Set up the initial notification state. mActivityLaunchAnimator = new ActivityLaunchAnimator( mStatusBarWindow, this, mNotificationPanel, @@ -1036,7 +1035,10 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationActivityStarter = new StatusBarNotificationActivityStarter( mContext, mNotificationPanel, mPresenter, mHeadsUpManager, mActivityLaunchAnimator); mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter); - mEntryManager.setNotificationActivityStarter(mNotificationActivityStarter); + + mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager); + mEntryManager.setNotificationClicker(new NotificationClicker( + this, Dependency.get(BubbleController.class), mNotificationActivityStarter)); } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index 904e5b99b0ab..7f0e435eb7da 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -231,6 +231,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { mEntryManager = new TestableNotificationEntryManager(mContext, mBarService); Dependency.get(InitController.class).executePostInitTasks(); mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mCallback, mHeadsUpManager); + mEntryManager.setNotificationClicker(mock(NotificationClicker.class)); setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL); } |