Merge changes I64ec5165,I8e56a88e,I1aa582cd,I8e1b0eb0,I16163b42 into tm-qpr-dev

* changes:
  Inline notif pipeline flag into NotifLogger
  Inline notif pipeline flag in NotifInterruptPrvdr
  Inline notif pipeline flag into NotifController
  Inline notif pipeline flag into new pipeline code
  Inline notif pipeline flag into ConvoNotifMgr
This commit is contained in:
Jeff DeCew
2022-07-06 14:21:14 +00:00
committed by Android (Google) Code Review
18 changed files with 34 additions and 491 deletions

View File

@@ -31,7 +31,6 @@ import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.inflation.BindEventManager
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
@@ -129,11 +128,9 @@ class AnimatedImageNotificationManager @Inject constructor(
*/
@SysUISingleton
class ConversationNotificationManager @Inject constructor(
private val bindEventManager: BindEventManager,
private val notificationGroupManager: NotificationGroupManagerLegacy,
bindEventManager: BindEventManager,
private val context: Context,
private val notifCollection: CommonNotifCollection,
private val featureFlags: NotifPipelineFlags,
@Main private val mainHandler: Handler
) {
// Need this state to be thread safe, since it's accessed from the ui thread
@@ -172,12 +169,10 @@ class ConversationNotificationManager @Inject constructor(
layout.setIsImportantConversation(important, false)
}
}
if (changed && !featureFlags.isNewPipelineEnabled()) {
notificationGroupManager.updateIsolation(entry)
}
}
}
}
fun onEntryViewBound(entry: NotificationEntry) {
if (!entry.ranking.isConversation) {
return

View File

@@ -578,12 +578,10 @@ public class NotifCollection implements Dumpable {
// TODO: (b/145659174) update the sbn's overrideGroupKey in
// NotificationEntry.setRanking instead of here once we fully migrate to the
// NewNotifPipeline
if (mNotifPipelineFlags.isNewPipelineEnabled()) {
final String newOverrideGroupKey = ranking.getOverrideGroupKey();
if (!Objects.equals(entry.getSbn().getOverrideGroupKey(),
newOverrideGroupKey)) {
entry.getSbn().setOverrideGroupKey(newOverrideGroupKey);
}
final String newOverrideGroupKey = ranking.getOverrideGroupKey();
if (!Objects.equals(entry.getSbn().getOverrideGroupKey(),
newOverrideGroupKey)) {
entry.getSbn().setOverrideGroupKey(newOverrideGroupKey);
}
} else {
if (currentEntriesWithoutRankings == null) {

View File

@@ -76,7 +76,6 @@ import javax.inject.Inject
*/
@SysUISingleton
class NotifPipeline @Inject constructor(
notifPipelineFlags: NotifPipelineFlags,
private val mNotifCollection: NotifCollection,
private val mShadeListBuilder: ShadeListBuilder,
private val mRenderStageManager: RenderStageManager
@@ -107,8 +106,6 @@ class NotifPipeline @Inject constructor(
return mNotifCollection.getEntry(key)
}
val isNewPipelineEnabled: Boolean = notifPipelineFlags.isNewPipelineEnabled()
/**
* Registers a lifetime extender. Lifetime extenders can cause notifications that have been
* dismissed or retracted by system server to be temporarily retained in the collection.

View File

@@ -127,14 +127,6 @@ public class BubbleCoordinator implements Coordinator {
DismissedByUserStats dismissedByUserStats,
int reason
) {
if (!mNotifPipeline.isNewPipelineEnabled()) {
// The `entry` will be from whichever pipeline is active, so if the old pipeline is
// running, make sure that we use the new pipeline's entry (if it still exists).
NotificationEntry newPipelineEntry = mNotifPipeline.getEntry(entry.getKey());
if (newPipelineEntry != null) {
entry = newPipelineEntry;
}
}
if (isInterceptingDismissal(entry)) {
mInterceptedDismissalEntries.remove(entry.getKey());
mOnEndDismissInterception.onEndDismissInterception(mDismissInterceptor, entry,

View File

@@ -72,9 +72,7 @@ class NotifCoordinatorsImpl @Inject constructor(
// pipeline, such as this DataStoreCoordinator which cannot be removed, as it's a critical
// glue between the pipeline and parts of SystemUI which depend on pipeline output via the
// NotifLiveDataStore.
if (notifPipelineFlags.isNewPipelineEnabled()) {
mCoordinators.add(dataStoreCoordinator)
}
mCoordinators.add(dataStoreCoordinator)
// Attach normal coordinators.
mCoordinators.add(hideLocallyDismissedNotifsCoordinator)
@@ -97,18 +95,14 @@ class NotifCoordinatorsImpl @Inject constructor(
if (notifPipelineFlags.isSmartspaceDedupingEnabled()) {
mCoordinators.add(smartspaceDedupingCoordinator)
}
if (notifPipelineFlags.isNewPipelineEnabled()) {
mCoordinators.add(headsUpCoordinator)
mCoordinators.add(gutsCoordinator)
mCoordinators.add(preparationCoordinator)
mCoordinators.add(remoteInputCoordinator)
}
mCoordinators.add(headsUpCoordinator)
mCoordinators.add(gutsCoordinator)
mCoordinators.add(preparationCoordinator)
mCoordinators.add(remoteInputCoordinator)
// Manually add Ordered Sections
// HeadsUp > FGS > People > Alerting > Silent > Minimized > Unknown/Default
if (notifPipelineFlags.isNewPipelineEnabled()) {
mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp
}
mOrderedSections.add(headsUpCoordinator.sectioner)
mOrderedSections.add(appOpsCoordinator.sectioner) // ForegroundService
mOrderedSections.add(conversationCoordinator.sectioner) // People
mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting

View File

@@ -65,13 +65,6 @@ class SmartspaceDedupingCoordinator @Inject constructor(
statusBarStateController.addCallback(statusBarStateListener)
smartspaceController.addListener(this::onNewSmartspaceTargets)
if (!pipeline.isNewPipelineEnabled) {
// TODO (b/173126564): Remove this once the old pipeline is no longer necessary
notificationLockscreenUserManager.addKeyguardNotificationSuppressor { entry ->
isDupedWithSmartspaceContent(entry)
}
}
recordStatusBarState(statusBarStateController.state)
}

View File

@@ -70,11 +70,9 @@ class ViewConfigCoordinator @Inject internal constructor(
override fun attach(pipeline: NotifPipeline) {
mPipeline = pipeline
if (pipeline.isNewPipelineEnabled) {
mLockscreenUserManager.addUserChangedListener(mUserChangedListener)
mConfigurationController.addCallback(this)
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback)
}
mLockscreenUserManager.addUserChangedListener(mUserChangedListener)
mConfigurationController.addCallback(this)
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback)
}
override fun onDensityOrFontScaleChanged() {

View File

@@ -22,7 +22,6 @@ import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -53,7 +52,6 @@ public class NotifPipelineInitializer implements Dumpable {
private final NotifInflaterImpl mNotifInflater;
private final DumpManager mDumpManager;
private final ShadeViewManagerFactory mShadeViewManagerFactory;
private final NotifPipelineFlags mNotifPipelineFlags;
@Inject
@@ -66,8 +64,7 @@ public class NotifPipelineInitializer implements Dumpable {
NotifCoordinators notifCoordinators,
NotifInflaterImpl notifInflater,
DumpManager dumpManager,
ShadeViewManagerFactory shadeViewManagerFactory,
NotifPipelineFlags notifPipelineFlags
ShadeViewManagerFactory shadeViewManagerFactory
) {
mPipelineWrapper = pipelineWrapper;
mGroupCoalescer = groupCoalescer;
@@ -78,7 +75,6 @@ public class NotifPipelineInitializer implements Dumpable {
mDumpManager = dumpManager;
mNotifInflater = notifInflater;
mShadeViewManagerFactory = shadeViewManagerFactory;
mNotifPipelineFlags = notifPipelineFlags;
}
/** Hooks the new pipeline up to NotificationManager */
@@ -91,26 +87,22 @@ public class NotifPipelineInitializer implements Dumpable {
mDumpManager.registerDumpable("NotifPipeline", this);
// Setup inflation
if (mNotifPipelineFlags.isNewPipelineEnabled()) {
mNotifInflater.setRowBinder(rowBinder);
}
mNotifInflater.setRowBinder(rowBinder);
// Wire up coordinators
mNotifPluggableCoordinators.attach(mPipelineWrapper);
// Wire up pipeline
if (mNotifPipelineFlags.isNewPipelineEnabled()) {
mShadeViewManagerFactory
.create(listContainer, stackController)
.attach(mRenderStageManager);
}
mShadeViewManagerFactory
.create(listContainer, stackController)
.attach(mRenderStageManager);
mRenderStageManager.attach(mListBuilder);
mListBuilder.attach(mNotifCollection);
mNotifCollection.attach(mGroupCoalescer);
mGroupCoalescer.attach(notificationService);
Log.d(TAG, "Notif pipeline initialized."
+ " rendering=" + mNotifPipelineFlags.isNewPipelineEnabled());
+ " rendering=" + true);
}
@Override

View File

@@ -226,10 +226,8 @@ public interface NotificationsModule {
static NotificationLogger provideNotificationLogger(
NotificationListener notificationListener,
@UiBackground Executor uiBgExecutor,
NotifPipelineFlags notifPipelineFlags,
NotifLiveDataStore notifLiveDataStore,
NotificationVisibilityProvider visibilityProvider,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
StatusBarStateController statusBarStateController,
NotificationLogger.ExpansionStateLogger expansionStateLogger,
@@ -237,10 +235,8 @@ public interface NotificationsModule {
return new NotificationLogger(
notificationListener,
uiBgExecutor,
notifPipelineFlags,
notifLiveDataStore,
visibilityProvider,
entryManager,
notifPipeline,
statusBarStateController,
expansionStateLogger,

View File

@@ -23,31 +23,22 @@ import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.Snoo
import com.android.systemui.statusbar.NotificationListener
import com.android.systemui.statusbar.NotificationPresenter
import com.android.systemui.statusbar.notification.AnimatedImageNotificationManager
import com.android.systemui.statusbar.notification.NotifPipelineFlags
import com.android.systemui.statusbar.notification.NotificationActivityStarter
import com.android.systemui.statusbar.notification.NotificationClicker
import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.NotificationListController
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager
import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
import com.android.systemui.statusbar.notification.collection.inflation.BindEventManagerImpl
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.provider.DebugModeFilterProvider
import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.interruption.HeadsUpController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.RemoteInputUriController
import com.android.wm.shell.bubbles.Bubbles
import dagger.Lazy
import java.io.PrintWriter
@@ -64,30 +55,21 @@ import javax.inject.Inject
@SysUISingleton
class NotificationsControllerImpl @Inject constructor(
private val centralSurfaces: Lazy<CentralSurfaces>,
private val notifPipelineFlags: NotifPipelineFlags,
private val notificationListener: NotificationListener,
private val entryManager: NotificationEntryManager,
private val debugModeFilterProvider: DebugModeFilterProvider,
private val legacyRanker: NotificationRankingManager,
private val commonNotifCollection: Lazy<CommonNotifCollection>,
private val notifPipeline: Lazy<NotifPipeline>,
private val notifLiveDataStore: NotifLiveDataStore,
private val targetSdkResolver: TargetSdkResolver,
private val newNotifPipelineInitializer: Lazy<NotifPipelineInitializer>,
private val notifPipelineInitializer: Lazy<NotifPipelineInitializer>,
private val notifBindPipelineInitializer: NotifBindPipelineInitializer,
private val deviceProvisionedController: DeviceProvisionedController,
private val notificationRowBinder: NotificationRowBinderImpl,
private val bindEventManagerImpl: BindEventManagerImpl,
private val remoteInputUriController: RemoteInputUriController,
private val groupManagerLegacy: Lazy<NotificationGroupManagerLegacy>,
private val groupAlertTransferHelper: NotificationGroupAlertTransferHelper,
private val headsUpManager: HeadsUpManager,
private val headsUpController: HeadsUpController,
private val headsUpViewBinder: HeadsUpViewBinder,
private val clickerBuilder: NotificationClicker.Builder,
private val animatedImageNotificationManager: AnimatedImageNotificationManager,
private val peopleSpaceWidgetManager: PeopleSpaceWidgetManager,
private val bubblesOptional: Optional<Bubbles>
private val bubblesOptional: Optional<Bubbles>,
) : NotificationsController {
override fun initialize(
@@ -118,33 +100,13 @@ class NotificationsControllerImpl @Inject constructor(
notifBindPipelineInitializer.initialize()
animatedImageNotificationManager.bind()
if (INITIALIZE_NEW_PIPELINE) {
newNotifPipelineInitializer.get().initialize(
notificationListener,
notificationRowBinder,
listContainer,
stackController)
}
notifPipelineInitializer.get().initialize(
notificationListener,
notificationRowBinder,
listContainer,
stackController)
if (notifPipelineFlags.isNewPipelineEnabled()) {
targetSdkResolver.initialize(notifPipeline.get())
// TODO
} else {
targetSdkResolver.initialize(entryManager)
remoteInputUriController.attach(entryManager)
groupAlertTransferHelper.bind(entryManager, groupManagerLegacy.get())
bindEventManagerImpl.attachToLegacyPipeline(entryManager)
headsUpManager.addListener(groupManagerLegacy.get())
headsUpManager.addListener(groupAlertTransferHelper)
headsUpController.attach(entryManager, headsUpManager)
groupManagerLegacy.get().setHeadsUpManager(headsUpManager)
groupAlertTransferHelper.setHeadsUpManager(headsUpManager)
debugModeFilterProvider.registerInvalidationListener {
entryManager.updateNotifications("debug mode filter changed")
}
entryManager.initialize(notificationListener, legacyRanker)
}
targetSdkResolver.initialize(notifPipeline.get())
peopleSpaceWidgetManager.attach(notificationListener)
}
@@ -185,9 +147,4 @@ class NotificationsControllerImpl @Inject constructor(
override fun getActiveNotificationsCount(): Int =
notifLiveDataStore.activeNotifCount.value
companion object {
// NOTE: The new pipeline is always active, even if the old pipeline is *rendering*.
private const val INITIALIZE_NEW_PIPELINE = true
}
}

View File

@@ -294,11 +294,6 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
* @return true if these checks pass, false if the notification should not alert
*/
private boolean canAlertCommon(NotificationEntry entry) {
if (!mFlags.isNewPipelineEnabled() && mNotificationFilter.shouldFilterOut(entry)) {
mLogger.logNoAlertingFilteredOut(entry);
return false;
}
for (int i = 0; i < mSuppressors.size(); i++) {
if (mSuppressors.get(i).suppressInterruptions(entry)) {
mLogger.logNoAlertingSuppressedBy(entry, mSuppressors.get(i), /* awake */ false);

View File

@@ -22,7 +22,6 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.Trace;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -39,9 +38,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -80,7 +76,6 @@ public class NotificationLogger implements StateListener {
private final Executor mUiBgExecutor;
private final NotifLiveDataStore mNotifLiveDataStore;
private final NotificationVisibilityProvider mVisibilityProvider;
private final NotificationEntryManager mEntryManager;
private final NotifPipeline mNotifPipeline;
private final NotificationPanelLogger mNotificationPanelLogger;
private final ExpansionStateLogger mExpansionStateLogger;
@@ -220,10 +215,8 @@ public class NotificationLogger implements StateListener {
*/
public NotificationLogger(NotificationListener notificationListener,
@UiBackground Executor uiBgExecutor,
NotifPipelineFlags notifPipelineFlags,
NotifLiveDataStore notifLiveDataStore,
NotificationVisibilityProvider visibilityProvider,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
StatusBarStateController statusBarStateController,
ExpansionStateLogger expansionStateLogger,
@@ -232,7 +225,6 @@ public class NotificationLogger implements StateListener {
mUiBgExecutor = uiBgExecutor;
mNotifLiveDataStore = notifLiveDataStore;
mVisibilityProvider = visibilityProvider;
mEntryManager = entryManager;
mNotifPipeline = notifPipeline;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -241,36 +233,7 @@ public class NotificationLogger implements StateListener {
// Not expected to be destroyed, don't need to unsubscribe
statusBarStateController.addCallback(this);
if (notifPipelineFlags.isNewPipelineEnabled()) {
registerNewPipelineListener();
} else {
registerLegacyListener();
}
}
private void registerLegacyListener() {
mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onEntryRemoved(
NotificationEntry entry,
NotificationVisibility visibility,
boolean removedByUser,
int reason) {
mExpansionStateLogger.onEntryRemoved(entry.getKey());
}
@Override
public void onPreEntryUpdated(NotificationEntry entry) {
mExpansionStateLogger.onEntryUpdated(entry.getKey());
}
@Override
public void onInflationError(
StatusBarNotification notification,
Exception exception) {
logNotificationError(notification, exception);
}
});
registerNewPipelineListener();
}
private void registerNewPipelineListener() {
@@ -333,26 +296,6 @@ public class NotificationLogger implements StateListener {
}
}
/**
* Logs Notification inflation error
*/
private void logNotificationError(
StatusBarNotification notification,
Exception exception) {
try {
mBarService.onNotificationError(
notification.getPackageName(),
notification.getTag(),
notification.getId(),
notification.getUid(),
notification.getInitialPid(),
exception.getMessage(),
notification.getUserId());
} catch (RemoteException ex) {
// The end is nigh.
}
}
private void logNotificationVisibilityChanges(
Collection<NotificationVisibility> newlyVisible,
Collection<NotificationVisibility> noLongerVisible) {

View File

@@ -152,8 +152,6 @@ public class NotifCollectionTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
allowTestableLooperAsMainThread();
when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(true);
when(mEulogizer.record(any(Exception.class))).thenAnswer(i -> i.getArguments()[0]);
mListenerInOrder = inOrder(mCollectionListener);

View File

@@ -60,7 +60,6 @@ class ViewConfigCoordinatorTest : SysuiTestCase() {
@Before
fun setUp() {
whenever(pipeline.isNewPipelineEnabled).thenReturn(true)
whenever(pipeline.allNotifs).thenReturn(listOf(entry))
whenever(entry.row).thenReturn(row)
coordinator = ViewConfigCoordinator(

View File

@@ -206,11 +206,9 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
@Test
public void testDoNotRunFilterOnNewPipeline() {
when(mFlags.isNewPipelineEnabled()).thenReturn(true);
// WHEN this entry should be filtered out
NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
mNotifInterruptionStateProvider.shouldHeadsUp(entry);
verify(mFlags, times(1)).isNewPipelineEnabled();
verify(mNotificationFilter, times(0)).shouldFilterOut(eq(entry));
}
@@ -326,7 +324,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
public void testShouldNotHeadsUp_filtered() throws RemoteException {
ensureStateForHeadsUpWhenAwake();
// Make canAlertCommon false by saying it's filtered out
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(true);
when(mKeyguardNotificationVisibilityProvider.shouldHideNotification(any()))
.thenReturn(true);
NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
@@ -504,7 +503,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
ensureStateForBubbleUp();
// Make canAlertCommon false by saying it's filtered out
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(true);
when(mKeyguardNotificationVisibilityProvider.shouldHideNotification(any()))
.thenReturn(true);
assertThat(mNotifInterruptionStateProvider.shouldBubbleUp(createBubble())).isFalse();
}

View File

@@ -1,299 +0,0 @@
/*
* Copyright (C) 2017 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.logging;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.InstanceId;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifLiveData;
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.logging.nano.Notifications;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import com.google.android.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class NotificationLoggerLegacyTest extends SysuiTestCase {
private static final String TEST_PACKAGE_NAME = "test";
private static final int TEST_UID = 0;
@Mock private NotificationListContainer mListContainer;
@Mock private IStatusBarService mBarService;
@Mock private ExpandableNotificationRow mRow;
@Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
// Dependency mocks:
@Mock private NotifPipelineFlags mNotifPipelineFlags;
@Mock private NotifLiveDataStore mNotifLiveDataStore;
@Mock private NotifLiveData<List<NotificationEntry>> mActiveNotifList;
@Mock private NotificationVisibilityProvider mVisibilityProvider;
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotifPipeline mNotifPipeline;
@Mock private NotificationListener mListener;
private NotificationEntry mEntry;
private TestableNotificationLogger mLogger;
private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>();
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private NotificationPanelLoggerFake mNotificationPanelLoggerFake =
new NotificationPanelLoggerFake();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mNotifLiveDataStore.getActiveNotifList()).thenReturn(mActiveNotifList);
mEntry = new NotificationEntryBuilder()
.setPkg(TEST_PACKAGE_NAME)
.setOpPkg(TEST_PACKAGE_NAME)
.setUid(TEST_UID)
.setNotification(new Notification())
.setUser(UserHandle.CURRENT)
.setInstanceId(InstanceId.fakeInstanceId(1))
.build();
mEntry.setRow(mRow);
mLogger = new TestableNotificationLogger(
mListener,
mUiBgExecutor,
mNotifPipelineFlags,
mNotifLiveDataStore,
mVisibilityProvider,
mEntryManager,
mNotifPipeline,
mock(StatusBarStateControllerImpl.class),
mBarService,
mExpansionStateLogger
);
mLogger.setUpWithContainer(mListContainer);
verify(mEntryManager).addNotificationEntryListener(any());
verify(mNotifPipeline, never()).addCollectionListener(any());
}
@After
public void tearDown() {
mLogger.mHandler.removeCallbacksAndMessages(null);
}
@Test
public void testOnChildLocationsChangedReportsVisibilityChanged() throws Exception {
NotificationVisibility[] newlyVisibleKeys = {
NotificationVisibility.obtain(mEntry.getKey(), 0, 1, true)
};
NotificationVisibility[] noLongerVisibleKeys = {};
doAnswer(invocation -> {
try {
assertArrayEquals(newlyVisibleKeys,
(NotificationVisibility[]) invocation.getArguments()[0]);
assertArrayEquals(noLongerVisibleKeys,
(NotificationVisibility[]) invocation.getArguments()[1]);
} catch (AssertionError error) {
mErrorQueue.offer(error);
}
return null;
}
).when(mBarService).onNotificationVisibilityChanged(any(NotificationVisibility[].class),
any(NotificationVisibility[].class));
when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
mUiBgExecutor.runAllReady();
if (!mErrorQueue.isEmpty()) {
throw mErrorQueue.poll();
}
// |mEntry| won't change visibility, so it shouldn't be reported again:
Mockito.reset(mBarService);
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
mUiBgExecutor.runAllReady();
verify(mBarService, never()).onNotificationVisibilityChanged(any(), any());
}
@Test
public void testStoppingNotificationLoggingReportsCurrentNotifications()
throws Exception {
when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
mUiBgExecutor.runAllReady();
Mockito.reset(mBarService);
setStateAsleep();
mLogger.onDozingChanged(false); // Wake to lockscreen
mLogger.onDozingChanged(true); // And go back to sleep, turning off logging
mUiBgExecutor.runAllReady();
// The visibility objects are recycled by NotificationLogger, so we can't use specific
// matchers here.
verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any());
}
private void setStateAsleep() {
mLogger.onPanelExpandedChanged(true);
mLogger.onDozingChanged(true);
mLogger.onStateChanged(StatusBarState.KEYGUARD);
}
private void setStateAwake() {
mLogger.onPanelExpandedChanged(false);
mLogger.onDozingChanged(false);
mLogger.onStateChanged(StatusBarState.SHADE);
}
@Test
public void testLogPanelShownOnWake() {
when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(mEntry));
setStateAsleep();
mLogger.onDozingChanged(false); // Wake to lockscreen
assertEquals(1, mNotificationPanelLoggerFake.getCalls().size());
assertTrue(mNotificationPanelLoggerFake.get(0).isLockscreen);
assertEquals(1, mNotificationPanelLoggerFake.get(0).list.notifications.length);
Notifications.Notification n = mNotificationPanelLoggerFake.get(0).list.notifications[0];
assertEquals(TEST_PACKAGE_NAME, n.packageName);
assertEquals(TEST_UID, n.uid);
assertEquals(1, n.instanceId);
assertFalse(n.isGroupSummary);
assertEquals(Notifications.Notification.SECTION_ALERTING, n.section);
}
@Test
public void testLogPanelShownOnShadePull() {
when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(mEntry));
setStateAwake();
// Now expand panel
mLogger.onPanelExpandedChanged(true);
assertEquals(1, mNotificationPanelLoggerFake.getCalls().size());
assertFalse(mNotificationPanelLoggerFake.get(0).isLockscreen);
assertEquals(1, mNotificationPanelLoggerFake.get(0).list.notifications.length);
Notifications.Notification n = mNotificationPanelLoggerFake.get(0).list.notifications[0];
assertEquals(TEST_PACKAGE_NAME, n.packageName);
assertEquals(TEST_UID, n.uid);
assertEquals(1, n.instanceId);
assertFalse(n.isGroupSummary);
assertEquals(Notifications.Notification.SECTION_ALERTING, n.section);
}
@Test
public void testLogPanelShownHandlesNullInstanceIds() {
// Construct a NotificationEntry like mEntry, but with a null instance id.
NotificationEntry entry = new NotificationEntryBuilder()
.setPkg(TEST_PACKAGE_NAME)
.setOpPkg(TEST_PACKAGE_NAME)
.setUid(TEST_UID)
.setNotification(new Notification())
.setUser(UserHandle.CURRENT)
.build();
entry.setRow(mRow);
when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(entry));
setStateAsleep();
mLogger.onDozingChanged(false); // Wake to lockscreen
assertEquals(1, mNotificationPanelLoggerFake.getCalls().size());
assertEquals(1, mNotificationPanelLoggerFake.get(0).list.notifications.length);
Notifications.Notification n = mNotificationPanelLoggerFake.get(0).list.notifications[0];
assertEquals(0, n.instanceId);
}
private class TestableNotificationLogger extends NotificationLogger {
TestableNotificationLogger(NotificationListener notificationListener,
Executor uiBgExecutor,
NotifPipelineFlags notifPipelineFlags,
NotifLiveDataStore notifLiveDataStore,
NotificationVisibilityProvider visibilityProvider,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
StatusBarStateControllerImpl statusBarStateController,
IStatusBarService barService,
ExpansionStateLogger expansionStateLogger) {
super(
notificationListener,
uiBgExecutor,
notifPipelineFlags,
notifLiveDataStore,
visibilityProvider,
entryManager,
notifPipeline,
statusBarStateController,
expansionStateLogger,
mNotificationPanelLoggerFake
);
mBarService = barService;
mHandler.removeCallbacksAndMessages(null);
// Make this on the current thread so we can wait for it during tests.
mHandler = Handler.createAsync(Looper.myLooper());
}
OnChildLocationsChangedListener getChildLocationsChangedListenerForTest() {
return mNotificationLocationsChangedListener;
}
}
}

View File

@@ -103,7 +103,6 @@ public class NotificationLoggerTest extends SysuiTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(true);
when(mNotifLiveDataStore.getActiveNotifList()).thenReturn(mActiveNotifEntries);
mEntry = new NotificationEntryBuilder()
@@ -278,10 +277,8 @@ public class NotificationLoggerTest extends SysuiTestCase {
super(
notificationListener,
uiBgExecutor,
notifPipelineFlags,
notifLiveDataStore,
visibilityProvider,
entryManager,
notifPipeline,
statusBarStateController,
expansionStateLogger,

View File

@@ -322,10 +322,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
NotificationLogger notificationLogger = new NotificationLogger(
mNotificationListener,
mUiBgExecutor,
mNotifPipelineFlags,
mNotifLiveDataStore,
mVisibilityProvider,
mock(NotificationEntryManager.class),
mock(NotifPipeline.class),
mStatusBarStateController,
mExpansionStateLogger,