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

Commit 85f7df62 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Make mPendingNotifications truly private"

parents 37a22b6c 294d0a21
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.systemui.statusbar.notification;

/**
 * Listener interface for when NotificationEntryManager needs to tell
 * NotificationGroupAlertTransferHelper things. Will eventually grow to be a general-purpose
 * listening interface for the NotificationEntryManager.
 */
public interface AlertTransferListener {
    /**
     * Called when a new notification is posted. At this point, the notification is "pending": its
     * views haven't been inflated yet and most of the system pretends like it doesn't exist yet.
     */
    void onPendingEntryAdded(NotificationData.Entry entry);

    /**
     * Called when an existing notification's views are reinflated (usually due to an update being
     * posted to that notification).
     */
    void onEntryReinflated(NotificationData.Entry entry);

    /**
     * Called when a notification has been removed (either because the user swiped it away or
     * because the developer retracted it).
     */
    void onEntryRemoved(NotificationData.Entry entry);
}
+23 −13
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.EventLogTags;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.bubbles.BubbleController;
@@ -83,7 +82,6 @@ import com.android.systemui.statusbar.notification.row.NotificationInflater;
import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -117,8 +115,6 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.

    private final NotificationGroupManager mGroupManager =
            Dependency.get(NotificationGroupManager.class);
    private final NotificationGroupAlertTransferHelper mGroupAlertTransferHelper =
            Dependency.get(NotificationGroupAlertTransferHelper.class);
    private final NotificationGutsManager mGutsManager =
            Dependency.get(NotificationGutsManager.class);
    private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -157,6 +153,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
            = new ArrayList<>();
    private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
    private NotificationViewHierarchyManager.StatusBarStateListener mStatusBarStateListener;
    @Nullable private AlertTransferListener mAlertTransferListener;

    private final class NotificationClicker implements View.OnClickListener {

@@ -258,12 +255,10 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
        mMessagingUtil = new NotificationMessagingUtil(context);
        mBubbleController.setDismissListener(this /* bubbleEventListener */);
        mNotificationData = new NotificationData();
        Dependency.get(InitController.class).addPostInitTask(this::onPostInit);
    }

    private void onPostInit() {
        mGroupAlertTransferHelper.setPendingEntries(mPendingNotifications);
        mGroupManager.addOnGroupChangeListener(mGroupAlertTransferHelper);
    public void setAlertTransferListener(AlertTransferListener listener) {
        mAlertTransferListener = listener;
    }

    /**
@@ -587,7 +582,9 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
                    mVisualStabilityManager.onLowPriorityUpdated(entry);
                    mPresenter.updateNotificationViews();
                }
                mGroupAlertTransferHelper.onInflationFinished(entry);
                if (mAlertTransferListener != null) {
                    mAlertTransferListener.onEntryReinflated(entry);
                }
            }
        }
        entry.setLowPriorityStateUpdated(false);
@@ -600,8 +597,12 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.

    private void removeNotificationInternal(String key,
            @Nullable NotificationListenerService.RankingMap ranking, boolean forceRemove) {
        final NotificationData.Entry entry = mNotificationData.get(key);

        abortExistingInflation(key);
        mGroupAlertTransferHelper.cleanUpPendingAlertInfo(key);
        if (mAlertTransferListener != null) {
            mAlertTransferListener.onEntryRemoved(entry);
        }

        // Attempt to remove notifications from their alert managers (heads up, ambient pulse).
        // Though the remove itself may fail, it lets the manager know to remove as soon as
@@ -620,8 +621,6 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
            mAmbientPulseManager.removeNotification(key, false /* ignoreEarliestRemovalTime */);
        }

        NotificationData.Entry entry = mNotificationData.get(key);

        if (entry == null) {
            mCallback.onNotificationRemoved(key, null /* old */);
            return;
@@ -846,7 +845,9 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
                mNotificationData.getImportance(key));

        mPendingNotifications.put(key, shadeEntry);
        mGroupAlertTransferHelper.onPendingEntryAdded(shadeEntry);
        if (mAlertTransferListener != null) {
            mAlertTransferListener.onPendingEntryAdded(shadeEntry);
        }
    }

    @VisibleForTesting
@@ -1230,6 +1231,15 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
        }
    }

    /**
     * @return An iterator for all "pending" notifications. Pending notifications are newly-posted
     * notifications whose views have not yet been inflated. In general, the system pretends like
     * these don't exist, although there are a couple exceptions.
     */
    public Iterable<NotificationData.Entry> getPendingNotificationsIterator() {
        return mPendingNotifications.values();
    }

    /**
     * Callback for NotificationEntryManager.
     */
+91 −90
Original line number Diff line number Diff line
@@ -29,7 +29,9 @@ import com.android.systemui.statusbar.AmbientPulseManager.OnAmbientChangedListen
import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.AlertTransferListener;
import com.android.systemui.statusbar.notification.NotificationData.Entry;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.NotificationInflater.AsyncInflationTask;
import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
import com.android.systemui.statusbar.phone.NotificationGroupManager.NotificationGroup;
@@ -38,8 +40,6 @@ import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Objects;

/**
@@ -47,8 +47,8 @@ import java.util.Objects;
 * {@link HeadsUpManager}, {@link AmbientPulseManager}. In particular, this class deals with keeping
 * the correct notification in a group alerting based off the group suppression.
 */
public class NotificationGroupAlertTransferHelper implements OnGroupChangeListener,
        OnHeadsUpChangedListener, OnAmbientChangedListener, StateListener {
public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedListener,
        OnAmbientChangedListener, StateListener {

    private static final long ALERT_TRANSFER_TIMEOUT = 300;

@@ -69,15 +69,7 @@ public class NotificationGroupAlertTransferHelper implements OnGroupChangeListen
    private final NotificationGroupManager mGroupManager =
            Dependency.get(NotificationGroupManager.class);

    // TODO(b/119637830): It would be good if GroupManager already had all pending notifications as
    // normal children (i.e. add notifications to GroupManager before inflation) so that we don't
    // have to have this dependency. We'd also have to worry less about the suppression not being up
    // to date.
    /**
     * Notifications that are currently inflating for the first time. Used to remove an incorrectly
     * alerting notification faster.
     */
    private HashMap<String, Entry> mPendingNotifications;
    private NotificationEntryManager mEntryManager;

    private boolean mIsDozing;

@@ -85,6 +77,23 @@ public class NotificationGroupAlertTransferHelper implements OnGroupChangeListen
        Dependency.get(StatusBarStateController.class).addCallback(this);
    }

    /** Causes the TransferHelper to register itself as a listener to the appropriate classes. */
    public void bind(NotificationEntryManager entryManager,
            NotificationGroupManager groupManager) {
        if (mEntryManager != null) {
            throw new IllegalStateException("Already bound.");
        }

        // TODO(b/119637830): It would be good if GroupManager already had all pending notifications
        // as normal children (i.e. add notifications to GroupManager before inflation) so that we
        // don't have to have this dependency. We'd also have to worry less about the suppression
        // not being up to date.
        mEntryManager = entryManager;

        mEntryManager.setAlertTransferListener(mAlertTransferListener);
        groupManager.addOnGroupChangeListener(mOnGroupChangeListener);
    }

    /**
     * Whether or not a notification has transferred its alert state to the notification and
     * the notification should alert after inflating.
@@ -97,25 +106,10 @@ public class NotificationGroupAlertTransferHelper implements OnGroupChangeListen
        return alertInfo != null && alertInfo.isStillValid();
    }

    /**
     * Removes any alerts pending on this entry. Note that this will not stop any inflation tasks
     * started by a transfer, so this should only be used as clean-up for when inflation is stopped
     * and the pending alert no longer needs to happen.
     *
     * @param key notification key that may have info that needs to be cleaned up
     */
    public void cleanUpPendingAlertInfo(@NonNull String key) {
        mPendingAlerts.remove(key);
    }

    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
        mHeadsUpManager = headsUpManager;
    }

    public void setPendingEntries(HashMap<String, Entry> pendingNotifications) {
        mPendingNotifications = pendingNotifications;
    }

    @Override
    public void onStateChanged(int newState) {}

@@ -130,6 +124,7 @@ public class NotificationGroupAlertTransferHelper implements OnGroupChangeListen
        mIsDozing = isDozing;
    }

    private final OnGroupChangeListener mOnGroupChangeListener = new OnGroupChangeListener() {
        @Override
        public void onGroupCreated(NotificationGroup group, String groupKey) {
            mGroupAlertEntries.put(groupKey, new GroupAlertEntry(group));
@@ -167,6 +162,7 @@ public class NotificationGroupAlertTransferHelper implements OnGroupChangeListen
                }
            }
        }
    };

    @Override
    public void onAmbientStateChanged(Entry entry, boolean isAmbient) {
@@ -185,37 +181,42 @@ public class NotificationGroupAlertTransferHelper implements OnGroupChangeListen
        }
    }

    /**
     * Called when the entry's reinflation has finished. If there is an alert pending, we then
     * show the alert.
     *
     * @param entry entry whose inflation has finished
     */
    public void onInflationFinished(@NonNull Entry entry) {
    private final AlertTransferListener mAlertTransferListener = new AlertTransferListener() {
        // Called when a new notification has been posted but is not inflated yet. We use this to
        // see as early as we can if we need to abort a transfer.
        @Override
        public void onPendingEntryAdded(Entry entry) {
            String groupKey = mGroupManager.getGroupKey(entry.notification);
            GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(groupKey);
            if (groupAlertEntry != null) {
                checkShouldTransferBack(groupAlertEntry);
            }
        }

        // Called when the entry's reinflation has finished. If there is an alert pending, we
        // then show the alert.
        @Override
        public void onEntryReinflated(Entry entry) {
            PendingAlertInfo alertInfo = mPendingAlerts.remove(entry.key);
            if (alertInfo != null) {
                if (alertInfo.isStillValid()) {
                    alertNotificationWhenPossible(entry, getActiveAlertManager());
                } else {
                    // The transfer is no longer valid. Free the content.
                entry.getRow().freeContentViewWhenSafe(alertInfo.mAlertManager.getContentFlag());
                    entry.getRow().freeContentViewWhenSafe(
                            alertInfo.mAlertManager.getContentFlag());
                }
            }
        }

    /**
     * Called when a new notification has been posted but is not inflated yet. We use this to see
     * as early as we can if we need to abort a transfer.
     *
     * @param entry entry that has been added
     */
    public void onPendingEntryAdded(@NonNull Entry entry) {
        String groupKey = mGroupManager.getGroupKey(entry.notification);
        GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(groupKey);
        if (groupAlertEntry != null) {
            checkShouldTransferBack(groupAlertEntry);
        }
        @Override
        public void onEntryRemoved(Entry entry) {
            // Removes any alerts pending on this entry. Note that this will not stop any inflation
            // tasks started by a transfer, so this should only be used as clean-up for when
            // inflation is stopped and the pending alert no longer needs to happen.
            mPendingAlerts.remove(entry.key);
        }
    };

    /**
     * Gets the number of new notifications pending inflation that will be added to the group
@@ -225,11 +226,11 @@ public class NotificationGroupAlertTransferHelper implements OnGroupChangeListen
     * @return the number of new notifications that will be added to the group
     */
    private int getPendingChildrenNotAlerting(@NonNull NotificationGroup group) {
        if (mPendingNotifications == null) {
        if (mEntryManager == null) {
            return 0;
        }
        int number = 0;
        Collection<Entry> values = mPendingNotifications.values();
        Iterable<Entry> values = mEntryManager.getPendingNotificationsIterator();
        for (Entry entry : values) {
            if (isPendingNotificationInGroup(entry, group) && onlySummaryAlerts(entry)) {
                number++;
@@ -245,10 +246,10 @@ public class NotificationGroupAlertTransferHelper implements OnGroupChangeListen
     * @return true if a pending notification will add to this group
     */
    private boolean pendingInflationsWillAddChildren(@NonNull NotificationGroup group) {
        if (mPendingNotifications == null) {
        if (mEntryManager == null) {
            return false;
        }
        Collection<Entry> values = mPendingNotifications.values();
        Iterable<Entry> values = mEntryManager.getPendingNotificationsIterator();
        for (Entry entry : values) {
            if (isPendingNotificationInGroup(entry, group)) {
                return true;
+2 −0
Original line number Diff line number Diff line
@@ -628,6 +628,8 @@ public class StatusBar extends SystemUI implements DemoMode,
        mBubbleController = Dependency.get(BubbleController.class);
        mBubbleController.setExpandListener(mBubbleExpandListener);

        mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager);

        mColorExtractor.addOnColorsChangedListener(this);
        mStatusBarStateController.addCallback(this, StatusBarStateController.RANK_STATUS_BAR);

+21 −10
Original line number Diff line number Diff line
@@ -32,14 +32,19 @@ import android.testing.TestableLooper;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.notification.AlertTransferListener;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationData.Entry;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

@@ -49,13 +54,15 @@ import java.util.HashMap;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {
    @Rule
    public MockitoRule rule = MockitoJUnit.rule();
    @Rule public MockitoRule rule = MockitoJUnit.rule();

    private NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
    private NotificationGroupManager mGroupManager;
    private AmbientPulseManager mAmbientPulseManager;
    private HeadsUpManager mHeadsUpManager;
    @Mock private NotificationEntryManager mNotificationEntryManager;
    @Captor private ArgumentCaptor<AlertTransferListener> mListenerCaptor;
    private AlertTransferListener mAlertTransferListener;
    private final HashMap<String, Entry> mPendingEntries = new HashMap<>();
    private final NotificationGroupTestHelper mGroupTestHelper =
            new NotificationGroupTestHelper(mContext);
@@ -67,15 +74,19 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {
        mDependency.injectTestDependency(AmbientPulseManager.class, mAmbientPulseManager);
        mHeadsUpManager = new HeadsUpManager(mContext) {};

        when(mNotificationEntryManager.getPendingNotificationsIterator())
                .thenReturn(mPendingEntries.values());

        mGroupManager = new NotificationGroupManager();
        mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
        mGroupManager.setHeadsUpManager(mHeadsUpManager);

        mGroupAlertTransferHelper = new NotificationGroupAlertTransferHelper();
        mGroupAlertTransferHelper.setHeadsUpManager(mHeadsUpManager);
        mGroupAlertTransferHelper.setPendingEntries(mPendingEntries);

        mGroupManager.addOnGroupChangeListener(mGroupAlertTransferHelper);
        mGroupAlertTransferHelper.bind(mNotificationEntryManager, mGroupManager);
        verify(mNotificationEntryManager).setAlertTransferListener(mListenerCaptor.capture());
        mAlertTransferListener = mListenerCaptor.getValue();
        mHeadsUpManager.addListener(mGroupAlertTransferHelper);
        mAmbientPulseManager.addListener(mGroupAlertTransferHelper);
    }
@@ -110,7 +121,7 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {

        // Add second child notification so that summary is no longer suppressed.
        mPendingEntries.put(childEntry2.key, childEntry2);
        mGroupAlertTransferHelper.onPendingEntryAdded(childEntry2);
        mAlertTransferListener.onPendingEntryAdded(childEntry2);
        mGroupManager.onEntryAdded(childEntry2);

        // The alert state should transfer back to the summary as there is now more than one
@@ -137,7 +148,7 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {

        // Add second child notification so that summary is no longer suppressed.
        mPendingEntries.put(childEntry2.key, childEntry2);
        mGroupAlertTransferHelper.onPendingEntryAdded(childEntry2);
        mAlertTransferListener.onPendingEntryAdded(childEntry2);
        mGroupManager.onEntryAdded(childEntry2);

        // Dozing changed so no reason to re-alert summary.
@@ -175,7 +186,7 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {

        when(childEntry.getRow().isInflationFlagSet(mHeadsUpManager.getContentFlag()))
            .thenReturn(true);
        mGroupAlertTransferHelper.onInflationFinished(childEntry);
        mAlertTransferListener.onEntryReinflated(childEntry);

        // Alert is immediately removed from summary, and we show child as its content is inflated.
        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.key));
@@ -199,13 +210,13 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {

        // Add second child notification so that summary is no longer suppressed.
        mPendingEntries.put(childEntry2.key, childEntry2);
        mGroupAlertTransferHelper.onPendingEntryAdded(childEntry2);
        mAlertTransferListener.onPendingEntryAdded(childEntry2);
        mGroupManager.onEntryAdded(childEntry2);

        // Child entry finishes its inflation.
        when(childEntry.getRow().isInflationFlagSet(mHeadsUpManager.getContentFlag()))
            .thenReturn(true);
        mGroupAlertTransferHelper.onInflationFinished(childEntry);
        mAlertTransferListener.onEntryReinflated(childEntry);

        verify(childEntry.getRow(), times(1)).freeContentViewWhenSafe(mHeadsUpManager
            .getContentFlag());
@@ -225,7 +236,7 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {
        mGroupManager.onEntryAdded(summaryEntry);
        mGroupManager.onEntryAdded(childEntry);

        mGroupAlertTransferHelper.cleanUpPendingAlertInfo(childEntry.key);
        mAlertTransferListener.onEntryRemoved(childEntry);

        assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
    }