Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea5be36f authored by Steve Elliott's avatar Steve Elliott
Browse files

Inline notif pipeline flag into NotifLogger

This change is a no-op; the flag is now enabled-by-default, so all
removed code paths here are effectively dead.

Bug: 200269355
Test: atest SystemUITests
Change-Id: I64ec51655efc0a4db7533880feba3e557c9686e5
parent 766b4077
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -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,
+1 −58
Original line number Diff line number Diff line
@@ -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);
            }
        });
    }

    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) {
+0 −299
Original line number Diff line number Diff line
/*
 * 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;
        }
    }
}
+0 −3
Original line number Diff line number Diff line
@@ -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,
+0 −2
Original line number Diff line number Diff line
@@ -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,