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

Commit c586467e authored by Ned Burns's avatar Ned Burns
Browse files

Invert dependency between NEM and RowBinder

NotificationEntryManager needs a NotificationRowBinder to inflate views
and bind them. Previously, it did this by calling Dependency.get(), but
this resulted in a circular dependency.

We can't fully break the circularity, but we can make it more explicit.
This CL inverts the dependency -- now the NEM needs someone else to give
it a row binder before it can function properly. Among other things,
this makes testing easier.

This CL allows us to isolate the interface between the NEM and NRB; in
later CLs we can make explicit the async inflation callback between the
NEM and the NRB and finally rewrite most of the NEM tests.

Test: atest
Change-Id: Ibb6ca4416456021a3c0a3679d1d74248fca18af6
parent 7b8c60e0
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationRowBinder;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
@@ -266,7 +265,6 @@ public class Dependency extends SystemUI {
    @Inject Lazy<NotificationListener> mNotificationListener;
    @Inject Lazy<NotificationLogger> mNotificationLogger;
    @Inject Lazy<NotificationViewHierarchyManager> mNotificationViewHierarchyManager;
    @Inject Lazy<NotificationRowBinder> mNotificationRowBinder;
    @Inject Lazy<NotificationFilter> mNotificationFilter;
    @Inject Lazy<NotificationInterruptionStateProvider> mNotificationInterruptionStateProvider;
    @Inject Lazy<KeyguardDismissUtil> mKeyguardDismissUtil;
@@ -440,7 +438,6 @@ public class Dependency extends SystemUI {
        mProviders.put(NotificationLogger.class, mNotificationLogger::get);
        mProviders.put(NotificationViewHierarchyManager.class,
                mNotificationViewHierarchyManager::get);
        mProviders.put(NotificationRowBinder.class, mNotificationRowBinder::get);
        mProviders.put(NotificationFilter.class, mNotificationFilter::get);
        mProviders.put(NotificationInterruptionStateProvider.class,
                mNotificationInterruptionStateProvider::get);
+1 −3
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
 */
package com.android.systemui.statusbar;

import com.android.systemui.statusbar.notification.NotificationRowBinder;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;

@@ -27,8 +26,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 * want to perform some action before doing so).
 */
public interface NotificationPresenter extends ExpandableNotificationRow.OnExpandClickListener,
        ActivatableNotificationView.OnActivatedListener,
        NotificationRowBinder.BindRowCallback {
        ActivatableNotificationView.OnActivatedListener {
    /**
     * Returns true if the presenter is not visible. For example, it may not be necessary to do
     * animations if this returns true.
+13 −13
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.NotificationUpdateHandler;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
@@ -124,16 +125,7 @@ public class NotificationEntryManager implements
        return mRemoteInputManager;
    }

    private NotificationRowBinder getRowBinder() {
        if (mNotificationRowBinder == null) {
            mNotificationRowBinder = Dependency.get(NotificationRowBinder.class);
        }
        return mNotificationRowBinder;
    }

    // TODO: Remove this once we can always use a mocked row binder in our tests
    @VisibleForTesting
    void setRowBinder(NotificationRowBinder notificationRowBinder) {
    public void setRowBinder(NotificationRowBinder notificationRowBinder) {
        mNotificationRowBinder = notificationRowBinder;
    }

@@ -345,7 +337,7 @@ public class NotificationEntryManager implements

        Dependency.get(LeakDetector.class).trackInstance(entry);
        // Construct the expanded view.
        getRowBinder().inflateViews(entry, () -> performRemoveNotification(notification));
        requireBinder().inflateViews(entry, () -> performRemoveNotification(notification));

        abortExistingInflation(key);

@@ -386,7 +378,7 @@ public class NotificationEntryManager implements
            listener.onPreEntryUpdated(entry);
        }

        getRowBinder().inflateViews(entry, () -> performRemoveNotification(notification));
        requireBinder().inflateViews(entry, () -> performRemoveNotification(notification));
        updateNotifications();

        if (DEBUG) {
@@ -440,7 +432,7 @@ public class NotificationEntryManager implements

        // By comparing the old and new UI adjustments, reinflate the view accordingly.
        for (NotificationEntry entry : entries) {
            getRowBinder().onNotificationRankingUpdated(
            requireBinder().onNotificationRankingUpdated(
                    entry,
                    oldImportances.get(entry.key),
                    oldAdjustments.get(entry.key),
@@ -486,4 +478,12 @@ public class NotificationEntryManager implements
            activeExtender.setShouldManageLifetime(entry, false);
        }
    }

    private NotificationRowBinder requireBinder() {
        if (mNotificationRowBinder == null) {
            throw new RuntimeException("You must initialize NotificationEntryManager by calling"
                    + "setRowBinder() before using.");
        }
        return mNotificationRowBinder;
    }
}
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.collection;

import android.annotation.Nullable;

import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationEntryManager;

/**
 * Used by the {@link NotificationEntryManager}. When notifications are added or updated, the binder
 * is asked to (re)inflate and prepare their views. This inflation must occur off the main thread.
 */
public interface NotificationRowBinder {
    /**
     * Called when a notification has been added or updated. The binder must asynchronously inflate
     * and bind the views associated with the notification.
     *
     * TODO: The caller is notified when the inflation completes, but this is currently a very
     * roundabout business. Add an explicit completion/failure callback to this method.
     */
    void inflateViews(
            NotificationEntry entry,
            Runnable onDismissRunnable)
            throws InflationException;

    /**
     * Called when the ranking has been updated (but not add or remove has been done). The binder
     * should inspect the old and new adjustments and re-inflate the entry's views if necessary
     * (e.g. if something important changed).
     */
    void onNotificationRankingUpdated(
            NotificationEntry entry,
            @Nullable Integer oldImportance,
            NotificationUiAdjustment oldAdjustment,
            NotificationUiAdjustment newAdjustment);
}
+9 −13
Original line number Diff line number Diff line
@@ -14,10 +14,9 @@
 * limitations under the License.
 */

package com.android.systemui.statusbar.notification;
package com.android.systemui.statusbar.notification.collection;

import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_AMBIENT;
import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
@@ -39,7 +38,9 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
@@ -50,13 +51,8 @@ import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

/** Handles inflating and updating views for notifications. */
@Singleton
public class NotificationRowBinder {
public class NotificationRowBinderImpl implements NotificationRowBinder {

    private static final String TAG = "NotificationViewManager";

@@ -84,9 +80,7 @@ public class NotificationRowBinder {
    private NotificationClicker mNotificationClicker;
    private final NotificationLogger mNotificationLogger = Dependency.get(NotificationLogger.class);

    @Inject
    public NotificationRowBinder(Context context,
            @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress) {
    public NotificationRowBinderImpl(Context context, boolean allowLongPress) {
        mContext = context;
        mMessagingUtil = new NotificationMessagingUtil(context);
        mAllowLongPress = allowLongPress;
@@ -122,6 +116,7 @@ public class NotificationRowBinder {
    /**
     * Inflates the views for the given entry (possibly asynchronously).
     */
    @Override
    public void inflateViews(
            NotificationEntry entry,
            Runnable onDismissRunnable)
@@ -192,6 +187,7 @@ public class NotificationRowBinder {
     * Updates the views bound to an entry when the entry's ranking changes, either in-place or by
     * reinflating them.
     */
    @Override
    public void onNotificationRankingUpdated(
            NotificationEntry entry,
            @Nullable Integer oldImportance,
Loading