Merge changes from topic "log-taps" into rvc-dev am: 81f5ea4077 am: ef43efe3b5

Change-Id: Ica277ae010a313f84291bc6bb2dd3c3ca55f7201
This commit is contained in:
Ned Burns
2020-04-21 23:12:05 +00:00
committed by Automerger Merge Worker
8 changed files with 487 additions and 162 deletions

View File

@@ -61,6 +61,18 @@ public class LogModule {
return buffer; return buffer;
} }
/** Provides a logging buffer for all logs related to the data layer of notifications. */
@Provides
@Singleton
@NotifInteractionLog
public static LogBuffer provideNotifInteractionLogBuffer(
LogcatEchoTracker echoTracker,
DumpManager dumpManager) {
LogBuffer buffer = new LogBuffer("NotifInteractionLog", 50, 10, echoTracker);
buffer.attach(dumpManager);
return buffer;
}
/** Provides a logging buffer for all logs related to Quick Settings. */ /** Provides a logging buffer for all logs related to Quick Settings. */
@Provides @Provides
@Singleton @Singleton

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2020 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.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import javax.inject.Qualifier;
/**
* A {@link LogBuffer} for messages related to the user interacting with notifications (e.g.
* clicking on them).
*/
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface NotifInteractionLog {
}

View File

@@ -23,11 +23,14 @@ import android.view.View;
import com.android.systemui.DejankUtils; import com.android.systemui.DejankUtils;
import com.android.systemui.bubbles.BubbleController; import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBar;
import java.util.Optional; import java.util.Optional;
import javax.inject.Inject;
/** /**
* Click handler for generic clicks on notifications. Clicks on specific areas (expansion caret, * Click handler for generic clicks on notifications. Clicks on specific areas (expansion caret,
* app ops icon, etc) are handled elsewhere. * app ops icon, etc) are handled elsewhere.
@@ -35,15 +38,19 @@ import java.util.Optional;
public final class NotificationClicker implements View.OnClickListener { public final class NotificationClicker implements View.OnClickListener {
private static final String TAG = "NotificationClicker"; private static final String TAG = "NotificationClicker";
private final Optional<StatusBar> mStatusBar;
private final BubbleController mBubbleController; private final BubbleController mBubbleController;
private final NotificationClickerLogger mLogger;
private final Optional<StatusBar> mStatusBar;
private final NotificationActivityStarter mNotificationActivityStarter; private final NotificationActivityStarter mNotificationActivityStarter;
public NotificationClicker(Optional<StatusBar> statusBar, private NotificationClicker(
BubbleController bubbleController, BubbleController bubbleController,
NotificationClickerLogger logger,
Optional<StatusBar> statusBar,
NotificationActivityStarter notificationActivityStarter) { NotificationActivityStarter notificationActivityStarter) {
mStatusBar = statusBar;
mBubbleController = bubbleController; mBubbleController = bubbleController;
mLogger = logger;
mStatusBar = statusBar;
mNotificationActivityStarter = notificationActivityStarter; mNotificationActivityStarter = notificationActivityStarter;
} }
@@ -58,25 +65,26 @@ public final class NotificationClicker implements View.OnClickListener {
SystemClock.uptimeMillis(), v, "NOTIFICATION_CLICK")); SystemClock.uptimeMillis(), v, "NOTIFICATION_CLICK"));
final ExpandableNotificationRow row = (ExpandableNotificationRow) v; final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
final StatusBarNotification sbn = row.getEntry().getSbn(); final NotificationEntry entry = row.getEntry();
if (sbn == null) { mLogger.logOnClick(entry);
Log.e(TAG, "NotificationClicker called on an unclickable notification,");
return;
}
// Check if the notification is displaying the menu, if so slide notification back // Check if the notification is displaying the menu, if so slide notification back
if (isMenuVisible(row)) { if (isMenuVisible(row)) {
mLogger.logMenuVisible(entry);
row.animateTranslateNotification(0); row.animateTranslateNotification(0);
return; return;
} else if (row.isChildInGroup() && isMenuVisible(row.getNotificationParent())) { } else if (row.isChildInGroup() && isMenuVisible(row.getNotificationParent())) {
mLogger.logParentMenuVisible(entry);
row.getNotificationParent().animateTranslateNotification(0); row.getNotificationParent().animateTranslateNotification(0);
return; return;
} else if (row.isSummaryWithChildren() && row.areChildrenExpanded()) { } else if (row.isSummaryWithChildren() && row.areChildrenExpanded()) {
// We never want to open the app directly if the user clicks in between // We never want to open the app directly if the user clicks in between
// the notifications. // the notifications.
mLogger.logChildrenExpanded(entry);
return; return;
} else if (row.areGutsExposed()) { } else if (row.areGutsExposed()) {
// ignore click if guts are exposed // ignore click if guts are exposed
mLogger.logGutsExposed(entry);
return; return;
} }
@@ -88,7 +96,7 @@ public final class NotificationClicker implements View.OnClickListener {
mBubbleController.collapseStack(); mBubbleController.collapseStack();
} }
mNotificationActivityStarter.onNotificationClicked(sbn, row); mNotificationActivityStarter.onNotificationClicked(entry.getSbn(), row);
} }
private boolean isMenuVisible(ExpandableNotificationRow row) { private boolean isMenuVisible(ExpandableNotificationRow row) {
@@ -107,4 +115,30 @@ public final class NotificationClicker implements View.OnClickListener {
row.setOnClickListener(null); row.setOnClickListener(null);
} }
} }
/** Daggerized builder for NotificationClicker. */
public static class Builder {
private final BubbleController mBubbleController;
private final NotificationClickerLogger mLogger;
@Inject
public Builder(
BubbleController bubbleController,
NotificationClickerLogger logger) {
mBubbleController = bubbleController;
mLogger = logger;
}
/** Builds an instance. */
public NotificationClicker build(
Optional<StatusBar> statusBar,
NotificationActivityStarter notificationActivityStarter
) {
return new NotificationClicker(
mBubbleController,
mLogger,
statusBar,
notificationActivityStarter);
}
}
} }

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2020 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 com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.NotifInteractionLog
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import javax.inject.Inject
class NotificationClickerLogger @Inject constructor(
@NotifInteractionLog private val buffer: LogBuffer
) {
fun logOnClick(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
str1 = entry.key
str2 = entry.ranking.channel.id
}, {
"CLICK $str1 (channel=$str2)"
})
}
fun logMenuVisible(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
str1 = entry.key
}, {
"Ignoring click on $str1; menu is visible"
})
}
fun logParentMenuVisible(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
str1 = entry.key
}, {
"Ignoring click on $str1; parent menu is visible"
})
}
fun logChildrenExpanded(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
str1 = entry.key
}, {
"Ignoring click on $str1; children are expanded"
})
}
fun logGutsExposed(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
str1 = entry.key
}, {
"Ignoring click on $str1; guts are exposed"
})
}
}
private const val TAG = "NotificationClicker"

View File

@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification.init package com.android.systemui.statusbar.notification.init
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import com.android.systemui.bubbles.BubbleController
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption
import com.android.systemui.statusbar.FeatureFlags import com.android.systemui.statusbar.FeatureFlags
import com.android.systemui.statusbar.NotificationListener import com.android.systemui.statusbar.NotificationListener
@@ -62,12 +61,12 @@ class NotificationsControllerImpl @Inject constructor(
private val deviceProvisionedController: DeviceProvisionedController, private val deviceProvisionedController: DeviceProvisionedController,
private val notificationRowBinder: NotificationRowBinderImpl, private val notificationRowBinder: NotificationRowBinderImpl,
private val remoteInputUriController: RemoteInputUriController, private val remoteInputUriController: RemoteInputUriController,
private val bubbleController: BubbleController,
private val groupManager: NotificationGroupManager, private val groupManager: NotificationGroupManager,
private val groupAlertTransferHelper: NotificationGroupAlertTransferHelper, private val groupAlertTransferHelper: NotificationGroupAlertTransferHelper,
private val headsUpManager: HeadsUpManager, private val headsUpManager: HeadsUpManager,
private val headsUpController: HeadsUpController, private val headsUpController: HeadsUpController,
private val headsUpViewBinder: HeadsUpViewBinder private val headsUpViewBinder: HeadsUpViewBinder,
private val clickerBuilder: NotificationClicker.Builder
) : NotificationsController { ) : NotificationsController {
override fun initialize( override fun initialize(
@@ -87,10 +86,7 @@ class NotificationsControllerImpl @Inject constructor(
listController.bind() listController.bind()
notificationRowBinder.setNotificationClicker( notificationRowBinder.setNotificationClicker(
NotificationClicker( clickerBuilder.build(Optional.of(statusBar), notificationActivityStarter))
Optional.of(statusBar),
bubbleController,
notificationActivityStarter))
notificationRowBinder.setUpWithPresenter( notificationRowBinder.setUpWithPresenter(
presenter, presenter,
listContainer, listContainer,

View File

@@ -40,7 +40,6 @@ import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.EventLog; import android.util.EventLog;
import android.util.Log;
import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationAdapter;
import android.view.View; import android.view.View;
@@ -91,92 +90,119 @@ import dagger.Lazy;
*/ */
public class StatusBarNotificationActivityStarter implements NotificationActivityStarter { public class StatusBarNotificationActivityStarter implements NotificationActivityStarter {
private static final String TAG = "NotifActivityStarter"; private final Context mContext;
protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final CommandQueue mCommandQueue;
private final Handler mMainThreadHandler;
private final Handler mBackgroundHandler;
private final Executor mUiBgExecutor;
private final Lazy<AssistManager> mAssistManagerLazy;
private final NotificationGroupManager mGroupManager;
private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback;
private final NotificationRemoteInputManager mRemoteInputManager;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final ShadeController mShadeController;
private final StatusBar mStatusBar;
private final KeyguardStateController mKeyguardStateController;
private final ActivityStarter mActivityStarter;
private final NotificationEntryManager mEntryManager; private final NotificationEntryManager mEntryManager;
private final NotifPipeline mNotifPipeline; private final NotifPipeline mNotifPipeline;
private final NotifCollection mNotifCollection; private final NotifCollection mNotifCollection;
private final FeatureFlags mFeatureFlags;
private final StatusBarStateController mStatusBarStateController;
private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final MetricsLogger mMetricsLogger;
private final Context mContext;
private final NotificationPanelViewController mNotificationPanel;
private final NotificationPresenter mPresenter;
private final LockPatternUtils mLockPatternUtils;
private final HeadsUpManagerPhone mHeadsUpManager; private final HeadsUpManagerPhone mHeadsUpManager;
private final ActivityStarter mActivityStarter;
private final IStatusBarService mBarService;
private final StatusBarStateController mStatusBarStateController;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final KeyguardManager mKeyguardManager; private final KeyguardManager mKeyguardManager;
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final IStatusBarService mBarService;
private final CommandQueue mCommandQueue;
private final IDreamManager mDreamManager; private final IDreamManager mDreamManager;
private final Handler mMainThreadHandler;
private final Handler mBackgroundHandler;
private final ActivityIntentHelper mActivityIntentHelper;
private final BubbleController mBubbleController; private final BubbleController mBubbleController;
private final Executor mUiBgExecutor; private final Lazy<AssistManager> mAssistManagerLazy;
private final NotificationRemoteInputManager mRemoteInputManager;
private final NotificationGroupManager mGroupManager;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final ShadeController mShadeController;
private final KeyguardStateController mKeyguardStateController;
private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final LockPatternUtils mLockPatternUtils;
private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback;
private final ActivityIntentHelper mActivityIntentHelper;
private final FeatureFlags mFeatureFlags;
private final MetricsLogger mMetricsLogger;
private final StatusBarNotificationActivityStarterLogger mLogger;
private final StatusBar mStatusBar;
private final NotificationPresenter mPresenter;
private final NotificationPanelViewController mNotificationPanel;
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private boolean mIsCollapsingToShowActivityOverLockscreen; private boolean mIsCollapsingToShowActivityOverLockscreen;
private StatusBarNotificationActivityStarter(Context context, CommandQueue commandQueue, private StatusBarNotificationActivityStarter(
Lazy<AssistManager> assistManagerLazy, NotificationPanelViewController panel, Context context,
NotificationPresenter presenter, NotificationEntryManager entryManager, CommandQueue commandQueue,
HeadsUpManagerPhone headsUpManager, ActivityStarter activityStarter, Handler mainThreadHandler,
ActivityLaunchAnimator activityLaunchAnimator, IStatusBarService statusBarService, Handler backgroundHandler,
Executor uiBgExecutor,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
NotifCollection notifCollection,
HeadsUpManagerPhone headsUpManager,
ActivityStarter activityStarter,
IStatusBarService statusBarService,
StatusBarStateController statusBarStateController, StatusBarStateController statusBarStateController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager, StatusBarKeyguardViewManager statusBarKeyguardViewManager,
KeyguardManager keyguardManager, KeyguardManager keyguardManager,
IDreamManager dreamManager, NotificationRemoteInputManager remoteInputManager, IDreamManager dreamManager,
StatusBarRemoteInputCallback remoteInputCallback, NotificationGroupManager groupManager, BubbleController bubbleController,
Lazy<AssistManager> assistManagerLazy,
NotificationRemoteInputManager remoteInputManager,
NotificationGroupManager groupManager,
NotificationLockscreenUserManager lockscreenUserManager, NotificationLockscreenUserManager lockscreenUserManager,
ShadeController shadeController, StatusBar statusBar, ShadeController shadeController,
KeyguardStateController keyguardStateController, KeyguardStateController keyguardStateController,
NotificationInterruptStateProvider notificationInterruptStateProvider, NotificationInterruptStateProvider notificationInterruptStateProvider,
MetricsLogger metricsLogger, LockPatternUtils lockPatternUtils, LockPatternUtils lockPatternUtils,
Handler mainThreadHandler, Handler backgroundHandler, Executor uiBgExecutor, StatusBarRemoteInputCallback remoteInputCallback,
ActivityIntentHelper activityIntentHelper, BubbleController bubbleController, ActivityIntentHelper activityIntentHelper,
FeatureFlags featureFlags, NotifPipeline notifPipeline,
NotifCollection notifCollection) { FeatureFlags featureFlags,
MetricsLogger metricsLogger,
StatusBarNotificationActivityStarterLogger logger,
StatusBar statusBar,
NotificationPresenter presenter,
NotificationPanelViewController panel,
ActivityLaunchAnimator activityLaunchAnimator) {
mContext = context; mContext = context;
mNotificationPanel = panel;
mPresenter = presenter;
mHeadsUpManager = headsUpManager;
mActivityLaunchAnimator = activityLaunchAnimator;
mBarService = statusBarService;
mCommandQueue = commandQueue; mCommandQueue = commandQueue;
mMainThreadHandler = mainThreadHandler;
mBackgroundHandler = backgroundHandler;
mUiBgExecutor = uiBgExecutor;
mEntryManager = entryManager;
mNotifPipeline = notifPipeline;
mNotifCollection = notifCollection;
mHeadsUpManager = headsUpManager;
mActivityStarter = activityStarter;
mBarService = statusBarService;
mStatusBarStateController = statusBarStateController;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mKeyguardManager = keyguardManager; mKeyguardManager = keyguardManager;
mDreamManager = dreamManager; mDreamManager = dreamManager;
mBubbleController = bubbleController;
mAssistManagerLazy = assistManagerLazy;
mRemoteInputManager = remoteInputManager; mRemoteInputManager = remoteInputManager;
mGroupManager = groupManager;
mLockscreenUserManager = lockscreenUserManager; mLockscreenUserManager = lockscreenUserManager;
mShadeController = shadeController; mShadeController = shadeController;
mKeyguardStateController = keyguardStateController;
mNotificationInterruptStateProvider = notificationInterruptStateProvider;
mLockPatternUtils = lockPatternUtils;
mStatusBarRemoteInputCallback = remoteInputCallback;
mActivityIntentHelper = activityIntentHelper;
mFeatureFlags = featureFlags;
mMetricsLogger = metricsLogger;
mLogger = logger;
// TODO: use KeyguardStateController#isOccluded to remove this dependency // TODO: use KeyguardStateController#isOccluded to remove this dependency
mStatusBar = statusBar; mStatusBar = statusBar;
mKeyguardStateController = keyguardStateController; mPresenter = presenter;
mActivityStarter = activityStarter; mNotificationPanel = panel;
mEntryManager = entryManager; mActivityLaunchAnimator = activityLaunchAnimator;
mStatusBarStateController = statusBarStateController;
mNotificationInterruptStateProvider = notificationInterruptStateProvider;
mMetricsLogger = metricsLogger;
mAssistManagerLazy = assistManagerLazy;
mGroupManager = groupManager;
mLockPatternUtils = lockPatternUtils;
mBackgroundHandler = backgroundHandler;
mUiBgExecutor = uiBgExecutor;
mFeatureFlags = featureFlags;
mNotifPipeline = notifPipeline;
mNotifCollection = notifCollection;
if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
mEntryManager.addNotificationEntryListener(new NotificationEntryListener() { mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override @Override
@@ -192,11 +218,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
} }
}); });
} }
mStatusBarRemoteInputCallback = remoteInputCallback;
mMainThreadHandler = mainThreadHandler;
mActivityIntentHelper = activityIntentHelper;
mBubbleController = bubbleController;
} }
/** /**
@@ -207,6 +228,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
*/ */
@Override @Override
public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) { public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
mLogger.logStartingActivityFromClick(sbn.getKey());
RemoteInputController controller = mRemoteInputManager.getController(); RemoteInputController controller = mRemoteInputManager.getController();
if (controller.isRemoteInputActive(row.getEntry()) if (controller.isRemoteInputActive(row.getEntry())
&& !TextUtils.isEmpty(row.getActiveRemoteInputText())) { && !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
@@ -225,7 +248,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
// The only valid case is Bubble notifications. Guard against other cases // The only valid case is Bubble notifications. Guard against other cases
// entering here. // entering here.
if (intent == null && !isBubble) { if (intent == null && !isBubble) {
Log.e(TAG, "onNotificationClicked called for non-clickable notification!"); mLogger.logNonClickableNotification(sbn.getKey());
return; return;
} }
@@ -258,6 +281,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
boolean isActivityIntent, boolean isActivityIntent,
boolean wasOccluded, boolean wasOccluded,
boolean showOverLockscreen) { boolean showOverLockscreen) {
mLogger.logHandleClickAfterKeyguardDismissed(sbn.getKey());
// TODO: Some of this code may be able to move to NotificationEntryManager. // TODO: Some of this code may be able to move to NotificationEntryManager.
if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(sbn.getKey())) { if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(sbn.getKey())) {
// Release the HUN notification to the shade. // Release the HUN notification to the shade.
@@ -304,6 +329,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
boolean isActivityIntent, boolean isActivityIntent,
boolean wasOccluded, boolean wasOccluded,
NotificationEntry parentToCancelFinal) { NotificationEntry parentToCancelFinal) {
mLogger.logHandleClickAfterPanelCollapsed(sbn.getKey());
String notificationKey = sbn.getKey(); String notificationKey = sbn.getKey();
try { try {
// The intent we are sending is for the application, which // The intent we are sending is for the application, which
@@ -343,9 +370,11 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
remoteInputText.toString()); remoteInputText.toString());
} }
if (isBubble) { if (isBubble) {
mLogger.logExpandingBubble(notificationKey);
expandBubbleStackOnMainThread(notificationKey); expandBubbleStackOnMainThread(notificationKey);
} else { } else {
startNotificationIntent(intent, fillInIntent, row, wasOccluded, isActivityIntent); startNotificationIntent(
intent, fillInIntent, entry, row, wasOccluded, isActivityIntent);
} }
if (isActivityIntent || isBubble) { if (isActivityIntent || isBubble) {
mAssistManagerLazy.get().hideAssist(); mAssistManagerLazy.get().hideAssist();
@@ -392,10 +421,16 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
} }
} }
private void startNotificationIntent(PendingIntent intent, Intent fillInIntent, private void startNotificationIntent(
View row, boolean wasOccluded, boolean isActivityIntent) { PendingIntent intent,
Intent fillInIntent,
NotificationEntry entry,
View row,
boolean wasOccluded,
boolean isActivityIntent) {
RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(row, RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(row,
wasOccluded); wasOccluded);
mLogger.logStartNotificationIntent(entry.getKey(), intent);
try { try {
if (adapter != null) { if (adapter != null) {
ActivityTaskManager.getService() ActivityTaskManager.getService()
@@ -408,7 +443,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
} catch (RemoteException | PendingIntent.CanceledException e) { } catch (RemoteException | PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here. // the stack trace isn't very helpful here.
// Just log the exception message. // Just log the exception message.
Log.w(TAG, "Sending contentIntent failed: " + e); mLogger.logSendingIntentFailed(e);
// TODO: Dismiss Keyguard. // TODO: Dismiss Keyguard.
} }
} }
@@ -438,13 +473,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private void handleFullScreenIntent(NotificationEntry entry) { private void handleFullScreenIntent(NotificationEntry entry) {
if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) { if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
if (shouldSuppressFullScreenIntent(entry)) { if (shouldSuppressFullScreenIntent(entry)) {
if (DEBUG) { mLogger.logFullScreenIntentSuppressedByDnD(entry.getKey());
Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.getKey());
}
} else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) { } else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
if (DEBUG) { mLogger.logFullScreenIntentNotImportantEnough(entry.getKey());
Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.getKey());
}
} else { } else {
// Stop screensaver if the notification has a fullscreen intent. // Stop screensaver if the notification has a fullscreen intent.
// (like an incoming phone call) // (like an incoming phone call)
@@ -457,13 +488,13 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}); });
// not immersive & a fullscreen alert should be shown // not immersive & a fullscreen alert should be shown
if (DEBUG) { final PendingIntent fullscreenIntent =
Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent"); entry.getSbn().getNotification().fullScreenIntent;
} mLogger.logSendingFullScreenIntent(entry.getKey(), fullscreenIntent);
try { try {
EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION, EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
entry.getKey()); entry.getKey());
entry.getSbn().getNotification().fullScreenIntent.send(); fullscreenIntent.send();
entry.notifyFullScreenIntentLaunched(); entry.notifyFullScreenIntentLaunched();
mMetricsLogger.count("note_fullscreen", 1); mMetricsLogger.count("note_fullscreen", 1);
} catch (PendingIntent.CanceledException e) { } catch (PendingIntent.CanceledException e) {
@@ -578,9 +609,10 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
public static class Builder { public static class Builder {
private final Context mContext; private final Context mContext;
private final CommandQueue mCommandQueue; private final CommandQueue mCommandQueue;
private final Lazy<AssistManager> mAssistManagerLazy; private final Handler mMainThreadHandler;
private final Handler mBackgroundHandler;
private final Executor mUiBgExecutor;
private final NotificationEntryManager mEntryManager; private final NotificationEntryManager mEntryManager;
private final FeatureFlags mFeatureFlags;
private final NotifPipeline mNotifPipeline; private final NotifPipeline mNotifPipeline;
private final NotifCollection mNotifCollection; private final NotifCollection mNotifCollection;
private final HeadsUpManagerPhone mHeadsUpManager; private final HeadsUpManagerPhone mHeadsUpManager;
@@ -590,30 +622,37 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final KeyguardManager mKeyguardManager; private final KeyguardManager mKeyguardManager;
private final IDreamManager mDreamManager; private final IDreamManager mDreamManager;
private final BubbleController mBubbleController;
private final Lazy<AssistManager> mAssistManagerLazy;
private final NotificationRemoteInputManager mRemoteInputManager; private final NotificationRemoteInputManager mRemoteInputManager;
private final StatusBarRemoteInputCallback mRemoteInputCallback;
private final NotificationGroupManager mGroupManager; private final NotificationGroupManager mGroupManager;
private final NotificationLockscreenUserManager mLockscreenUserManager; private final NotificationLockscreenUserManager mLockscreenUserManager;
private final KeyguardStateController mKeyguardStateController;
private final MetricsLogger mMetricsLogger;
private final LockPatternUtils mLockPatternUtils;
private final Handler mMainThreadHandler;
private final Handler mBackgroundHandler;
private final Executor mUiBgExecutor;
private final ActivityIntentHelper mActivityIntentHelper;
private final BubbleController mBubbleController;
private NotificationPanelViewController mNotificationPanelViewController;
private NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final ShadeController mShadeController; private final ShadeController mShadeController;
private NotificationPresenter mNotificationPresenter; private final KeyguardStateController mKeyguardStateController;
private ActivityLaunchAnimator mActivityLaunchAnimator; private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final LockPatternUtils mLockPatternUtils;
private final StatusBarRemoteInputCallback mRemoteInputCallback;
private final ActivityIntentHelper mActivityIntentHelper;
private final FeatureFlags mFeatureFlags;
private final MetricsLogger mMetricsLogger;
private final StatusBarNotificationActivityStarterLogger mLogger;
private StatusBar mStatusBar; private StatusBar mStatusBar;
private NotificationPresenter mNotificationPresenter;
private NotificationPanelViewController mNotificationPanelViewController;
private ActivityLaunchAnimator mActivityLaunchAnimator;
@Inject @Inject
public Builder(Context context, public Builder(
Context context,
CommandQueue commandQueue, CommandQueue commandQueue,
Lazy<AssistManager> assistManagerLazy, @Main Handler mainThreadHandler,
@Background Handler backgroundHandler,
@UiBackground Executor uiBgExecutor,
NotificationEntryManager entryManager, NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
NotifCollection notifCollection,
HeadsUpManagerPhone headsUpManager, HeadsUpManagerPhone headsUpManager,
ActivityStarter activityStarter, ActivityStarter activityStarter,
IStatusBarService statusBarService, IStatusBarService statusBarService,
@@ -621,27 +660,30 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
StatusBarKeyguardViewManager statusBarKeyguardViewManager, StatusBarKeyguardViewManager statusBarKeyguardViewManager,
KeyguardManager keyguardManager, KeyguardManager keyguardManager,
IDreamManager dreamManager, IDreamManager dreamManager,
BubbleController bubbleController,
Lazy<AssistManager> assistManagerLazy,
NotificationRemoteInputManager remoteInputManager, NotificationRemoteInputManager remoteInputManager,
StatusBarRemoteInputCallback remoteInputCallback,
NotificationGroupManager groupManager, NotificationGroupManager groupManager,
NotificationLockscreenUserManager lockscreenUserManager, NotificationLockscreenUserManager lockscreenUserManager,
ShadeController shadeController,
KeyguardStateController keyguardStateController, KeyguardStateController keyguardStateController,
NotificationInterruptStateProvider notificationInterruptStateProvider, NotificationInterruptStateProvider notificationInterruptStateProvider,
MetricsLogger metricsLogger,
LockPatternUtils lockPatternUtils, LockPatternUtils lockPatternUtils,
@Main Handler mainThreadHandler, StatusBarRemoteInputCallback remoteInputCallback,
@Background Handler backgroundHandler,
@UiBackground Executor uiBgExecutor,
ActivityIntentHelper activityIntentHelper, ActivityIntentHelper activityIntentHelper,
BubbleController bubbleController,
ShadeController shadeController,
FeatureFlags featureFlags, FeatureFlags featureFlags,
NotifPipeline notifPipeline, MetricsLogger metricsLogger,
NotifCollection notifCollection) { StatusBarNotificationActivityStarterLogger logger) {
mContext = context; mContext = context;
mCommandQueue = commandQueue; mCommandQueue = commandQueue;
mAssistManagerLazy = assistManagerLazy; mMainThreadHandler = mainThreadHandler;
mBackgroundHandler = backgroundHandler;
mUiBgExecutor = uiBgExecutor;
mEntryManager = entryManager; mEntryManager = entryManager;
mNotifPipeline = notifPipeline;
mNotifCollection = notifCollection;
mHeadsUpManager = headsUpManager; mHeadsUpManager = headsUpManager;
mActivityStarter = activityStarter; mActivityStarter = activityStarter;
mStatusBarService = statusBarService; mStatusBarService = statusBarService;
@@ -649,23 +691,21 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mKeyguardManager = keyguardManager; mKeyguardManager = keyguardManager;
mDreamManager = dreamManager; mDreamManager = dreamManager;
mBubbleController = bubbleController;
mAssistManagerLazy = assistManagerLazy;
mRemoteInputManager = remoteInputManager; mRemoteInputManager = remoteInputManager;
mRemoteInputCallback = remoteInputCallback;
mGroupManager = groupManager; mGroupManager = groupManager;
mLockscreenUserManager = lockscreenUserManager; mLockscreenUserManager = lockscreenUserManager;
mShadeController = shadeController;
mKeyguardStateController = keyguardStateController; mKeyguardStateController = keyguardStateController;
mNotificationInterruptStateProvider = notificationInterruptStateProvider; mNotificationInterruptStateProvider = notificationInterruptStateProvider;
mMetricsLogger = metricsLogger;
mLockPatternUtils = lockPatternUtils; mLockPatternUtils = lockPatternUtils;
mMainThreadHandler = mainThreadHandler; mRemoteInputCallback = remoteInputCallback;
mBackgroundHandler = backgroundHandler;
mUiBgExecutor = uiBgExecutor;
mActivityIntentHelper = activityIntentHelper; mActivityIntentHelper = activityIntentHelper;
mBubbleController = bubbleController;
mShadeController = shadeController;
mFeatureFlags = featureFlags; mFeatureFlags = featureFlags;
mNotifPipeline = notifPipeline; mMetricsLogger = metricsLogger;
mNotifCollection = notifCollection; mLogger = logger;
} }
/** Sets the status bar to use as {@link StatusBar}. */ /** Sets the status bar to use as {@link StatusBar}. */
@@ -692,37 +732,42 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
} }
public StatusBarNotificationActivityStarter build() { public StatusBarNotificationActivityStarter build() {
return new StatusBarNotificationActivityStarter(mContext, return new StatusBarNotificationActivityStarter(
mCommandQueue, mAssistManagerLazy, mContext,
mNotificationPanelViewController, mCommandQueue,
mNotificationPresenter, mMainThreadHandler,
mBackgroundHandler,
mUiBgExecutor,
mEntryManager, mEntryManager,
mNotifPipeline,
mNotifCollection,
mHeadsUpManager, mHeadsUpManager,
mActivityStarter, mActivityStarter,
mActivityLaunchAnimator,
mStatusBarService, mStatusBarService,
mStatusBarStateController, mStatusBarStateController,
mStatusBarKeyguardViewManager, mStatusBarKeyguardViewManager,
mKeyguardManager, mKeyguardManager,
mDreamManager, mDreamManager,
mBubbleController,
mAssistManagerLazy,
mRemoteInputManager, mRemoteInputManager,
mRemoteInputCallback,
mGroupManager, mGroupManager,
mLockscreenUserManager, mLockscreenUserManager,
mShadeController, mShadeController,
mStatusBar,
mKeyguardStateController, mKeyguardStateController,
mNotificationInterruptStateProvider, mNotificationInterruptStateProvider,
mMetricsLogger,
mLockPatternUtils, mLockPatternUtils,
mMainThreadHandler, mRemoteInputCallback,
mBackgroundHandler,
mUiBgExecutor,
mActivityIntentHelper, mActivityIntentHelper,
mBubbleController,
mFeatureFlags, mFeatureFlags,
mNotifPipeline, mMetricsLogger,
mNotifCollection); mLogger,
mStatusBar,
mNotificationPresenter,
mNotificationPanelViewController,
mActivityLaunchAnimator);
} }
} }
} }

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2020 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.phone
import android.app.PendingIntent
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.LogLevel.ERROR
import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.LogLevel.WARNING
import com.android.systemui.log.dagger.NotifInteractionLog
import javax.inject.Inject
class StatusBarNotificationActivityStarterLogger @Inject constructor(
@NotifInteractionLog private val buffer: LogBuffer
) {
fun logStartingActivityFromClick(key: String) {
buffer.log(TAG, DEBUG, {
str1 = key
}, {
"(1/4) onNotificationClicked: $str1"
})
}
fun logHandleClickAfterKeyguardDismissed(key: String) {
buffer.log(TAG, DEBUG, {
str1 = key
}, {
"(2/4) handleNotificationClickAfterKeyguardDismissed: $str1"
})
}
fun logHandleClickAfterPanelCollapsed(key: String) {
buffer.log(TAG, DEBUG, {
str1 = key
}, {
"(3/4) handleNotificationClickAfterPanelCollapsed: $str1"
})
}
fun logStartNotificationIntent(key: String, pendingIntent: PendingIntent) {
buffer.log(TAG, INFO, {
str1 = key
str2 = pendingIntent.intent.toString()
}, {
"(4/4) Starting $str2 for notification $str1"
})
}
fun logExpandingBubble(key: String) {
buffer.log(TAG, DEBUG, {
str1 = key
}, {
"Expanding bubble for $str1 (rather than firing intent)"
})
}
fun logSendingIntentFailed(e: Exception) {
buffer.log(TAG, WARNING, {
str1 = e.toString()
}, {
"Sending contentIntentFailed: $str1"
})
}
fun logNonClickableNotification(key: String) {
buffer.log(TAG, ERROR, {
str1 = key
}, {
"onNotificationClicked called for non-clickable notification! $str1"
})
}
fun logFullScreenIntentSuppressedByDnD(key: String) {
buffer.log(TAG, DEBUG, {
str1 = key
}, {
"No Fullscreen intent: suppressed by DND: $str1"
})
}
fun logFullScreenIntentNotImportantEnough(key: String) {
buffer.log(TAG, DEBUG, {
str1 = key
}, {
"No Fullscreen intent: not important enough: $str1"
})
}
fun logSendingFullScreenIntent(key: String, pendingIntent: PendingIntent) {
buffer.log(TAG, INFO, {
str1 = key
str2 = pendingIntent.intent.toString()
}, {
"Notification $str1 has fullScreenIntent; sending fullScreenIntent $str2"
})
}
}
private const val TAG = "NotifActivityStarter"

View File

@@ -176,25 +176,43 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE); when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false); when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
mNotificationActivityStarter = (new StatusBarNotificationActivityStarter.Builder( mNotificationActivityStarter =
getContext(), mock(CommandQueue.class), () -> mAssistManager, new StatusBarNotificationActivityStarter.Builder(
mEntryManager, mock(HeadsUpManagerPhone.class), getContext(),
mActivityStarter, mStatusBarService, mock(CommandQueue.class),
mock(StatusBarStateController.class), mStatusBarKeyguardViewManager, mHandler,
mock(KeyguardManager.class), mHandler,
mock(IDreamManager.class), mRemoteInputManager, mUiBgExecutor,
mock(StatusBarRemoteInputCallback.class), mock(NotificationGroupManager.class), mEntryManager,
mock(NotificationLockscreenUserManager.class), mNotifPipeline,
mKeyguardStateController, mNotifCollection,
mock(NotificationInterruptStateProvider.class), mock(MetricsLogger.class), mock(HeadsUpManagerPhone.class),
mock(LockPatternUtils.class), mHandler, mHandler, mUiBgExecutor, mActivityStarter,
mActivityIntentHelper, mBubbleController, mShadeController, mFeatureFlags, mStatusBarService,
mNotifPipeline, mNotifCollection) mock(StatusBarStateController.class),
mStatusBarKeyguardViewManager,
mock(KeyguardManager.class),
mock(IDreamManager.class),
mBubbleController,
() -> mAssistManager,
mRemoteInputManager,
mock(NotificationGroupManager.class),
mock(NotificationLockscreenUserManager.class),
mShadeController,
mKeyguardStateController,
mock(NotificationInterruptStateProvider.class),
mock(LockPatternUtils.class),
mock(StatusBarRemoteInputCallback.class),
mActivityIntentHelper,
mFeatureFlags,
mock(MetricsLogger.class),
mock(StatusBarNotificationActivityStarterLogger.class))
.setStatusBar(mStatusBar) .setStatusBar(mStatusBar)
.setNotificationPanelViewController(mock(NotificationPanelViewController.class))
.setNotificationPresenter(mock(NotificationPresenter.class)) .setNotificationPresenter(mock(NotificationPresenter.class))
.setActivityLaunchAnimator(mock(ActivityLaunchAnimator.class))) .setNotificationPanelViewController(mock(NotificationPanelViewController.class))
.build(); .setActivityLaunchAnimator(mock(ActivityLaunchAnimator.class))
.build();
// set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg // set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
doAnswer(mCallOnDismiss).when(mActivityStarter).dismissKeyguardThenExecute( doAnswer(mCallOnDismiss).when(mActivityStarter).dismissKeyguardThenExecute(