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

Commit 2630dc7e authored by Selim Cinek's avatar Selim Cinek
Browse files

Moved notification builder creation to the background

In preparation of future colorization work, the creation
of the notification builder is moved to the background.

Test: manual, add notifications, update them etc.
Test: runtest systemui
Bug: 36561228
Merged-In: Iaec5febf4d8d9da348d77e0d4f6f61b9746fae16
Change-Id: Iaec5febf4d8d9da348d77e0d4f6f61b9746fae16
parent 885b5f44
Loading
Loading
Loading
Loading
+12 −10
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package com.android.systemui.statusbar;

import static com.android.systemui.statusbar.notification.NotificationInflater.InflationExceptionHandler;
import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -47,6 +47,7 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RemoteViews;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.NotificationColorUtil;
@@ -61,7 +62,6 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.statusbar.NotificationGuts.GutsContent;
import com.android.systemui.statusbar.notification.HybridNotificationView;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationInflater;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
@@ -314,14 +314,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        }
    }

    public void updateNotification(NotificationData.Entry entry) throws InflationException {
    public void updateNotification(NotificationData.Entry entry) {
        mEntry = entry;
        mStatusBarNotification = entry.notification;
        mNotificationInflater.inflateNotificationViews();
        onNotificationUpdated();
    }

    private void onNotificationUpdated() {
    public void onNotificationUpdated() {
        for (NotificationContentView l : mLayouts) {
            l.onNotificationUpdated(mEntry);
        }
@@ -482,9 +481,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        boolean childInGroup = StatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
        mNotificationParent = childInGroup ? parent : null;
        mPrivateLayout.setIsChildInGroup(childInGroup);
        if (mNotificationInflater.setIsChildInGroup(childInGroup)) {
            onNotificationUpdated();
        }
        mNotificationInflater.setIsChildInGroup(childInGroup);
        resetBackgroundAlpha();
        updateBackgroundForGroupState();
        updateClickAndFocus();
@@ -1111,14 +1108,19 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        mNotificationInflater.setRemoteViewClickHandler(remoteViewClickHandler);
    }

    public void setInflateExceptionHandler(InflationExceptionHandler inflateExceptionHandler) {
        mNotificationInflater.setInflateExceptionHandler(inflateExceptionHandler);
    public void setInflationCallback(InflationCallback callback) {
        mNotificationInflater.setInflationCallback(callback);
    }

    public void setNeedsRedaction(boolean needsRedaction) {
        mNotificationInflater.setRedactAmbient(needsRedaction);
    }

    @VisibleForTesting
    public NotificationInflater getNotificationInflater() {
        return mNotificationInflater;
    }

    public interface ExpansionLogger {
        public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
    }
+19 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
@@ -32,6 +33,7 @@ import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.view.View;
import android.widget.ImageView;
import android.widget.RemoteViews;
@@ -41,6 +43,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationInflater;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -83,6 +86,7 @@ public class NotificationData {
        public List<SnoozeCriterion> snoozeCriteria;
        private int mCachedContrastColor = COLOR_INVALID;
        private int mCachedContrastColorIsFor = COLOR_INVALID;
        private ArraySet<AsyncTask> mRunningTasks = new ArraySet();

        public Entry(StatusBarNotification n) {
            this.key = n.getKey();
@@ -210,6 +214,19 @@ public class NotificationData {
            mCachedContrastColor = contrasted;
            return mCachedContrastColor;
        }

        /**
         * Abort all existing inflation tasks
         */
        public void abortInflation() {
            for (AsyncTask task : mRunningTasks) {
                task.cancel(true /* mayInterruptIfRunning */);
            }
        }

        public void addInflationTask(AsyncTask asyncInflationTask) {
            mRunningTasks.add(asyncInflationTask);
        }
    }

    private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
@@ -302,12 +319,12 @@ public class NotificationData {
        return mEntries.get(key);
    }

    public void add(Entry entry, RankingMap ranking) {
    public void add(Entry entry) {
        synchronized (mEntries) {
            mEntries.put(entry.notification.getKey(), entry);
        }
        mGroupManager.onEntryAdded(entry);
        updateRankingAndSort(ranking);
        filterAndSort();
    }

    public Entry remove(String key, RankingMap ranking) {
+83 −44
Original line number Diff line number Diff line
@@ -18,11 +18,10 @@ package com.android.systemui.statusbar.notification;

import android.app.Notification;
import android.content.Context;
import android.os.AsyncTask;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.RemoteViews;

import com.android.internal.annotations.VisibleForTesting;
@@ -39,7 +38,8 @@ public class NotificationInflater {
    @VisibleForTesting
    static final int FLAG_REINFLATE_ALL = ~0;
    private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0;
    private static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1;
    @VisibleForTesting
    static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1;
    private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2;
    private static final int FLAG_REINFLATE_PUBLIC_VIEW = 1<<3;
    private static final int FLAG_REINFLATE_AMBIENT_VIEW = 1<<4;
@@ -50,7 +50,7 @@ public class NotificationInflater {
    private boolean mUsesIncreasedHeadsUpHeight;
    private RemoteViews.OnClickHandler mRemoteViewClickHandler;
    private boolean mIsChildInGroup;
    private InflationExceptionHandler mInflateExceptionHandler;
    private InflationCallback mCallback;
    private boolean mRedactAmbient;

    public NotificationInflater(ExpandableNotificationRow row) {
@@ -66,21 +66,14 @@ public class NotificationInflater {
     *
     * @return whether the view was re-inflated
     */
    public boolean setIsChildInGroup(boolean childInGroup) {
    public void setIsChildInGroup(boolean childInGroup) {
        if (childInGroup != mIsChildInGroup) {
            mIsChildInGroup = childInGroup;
            if (mIsLowPriority) {
                try {
                int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW;
                inflateNotificationViews(flags);
                } catch (InflationException e) {
                    mInflateExceptionHandler.handleInflationException(
                            mRow.getStatusBarNotification(), e);
                }
            }
            return true;
        }
        return false;
        } ;
    }

    public void setUsesIncreasedHeight(boolean usesIncreasedHeight) {
@@ -101,39 +94,29 @@ public class NotificationInflater {
            if (mRow.getEntry() == null) {
                return;
            }
            try {
            inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW);
            } catch (InflationException e) {
                mInflateExceptionHandler.handleInflationException(
                        mRow.getStatusBarNotification(), e);
            }
        }
    }

    public void inflateNotificationViews() throws InflationException {
    /**
     * Inflate all views of this notification on a background thread. This is asynchronous and will
     * notify the callback once it's finished.
     */
    public void inflateNotificationViews() {
        inflateNotificationViews(FLAG_REINFLATE_ALL);
    }

    /**
     * reinflate all views for the specified flags
     * Reinflate all views for the specified flags on a background thread. This is asynchronous and
     * will notify the callback once it's finished.
     *
     * @param reInflateFlags flags which views should be reinflated. Use {@link #FLAG_REINFLATE_ALL}
     *                       to reinflate all of views.
     * @throws InflationException
     */
    private void inflateNotificationViews(int reInflateFlags)
            throws InflationException {
    @VisibleForTesting
    void inflateNotificationViews(int reInflateFlags) {
        StatusBarNotification sbn = mRow.getEntry().notification;
        try {
            final Notification.Builder recoveredBuilder
                    = Notification.Builder.recoverBuilder(mRow.getContext(), sbn.getNotification());
            Context packageContext = sbn.getPackageContext(mRow.getContext());
            inflateNotificationViews(reInflateFlags, recoveredBuilder, packageContext);

        } catch (RuntimeException e) {
            final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
            Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
            throw new InflationException("Couldn't inflate contentViews");
        }
        new AsyncInflationTask(mRow.getContext(), sbn, reInflateFlags).execute();
    }

    @VisibleForTesting
@@ -284,12 +267,13 @@ public class NotificationInflater {
                        && a.getLayoutId() == b.getLayoutId());
    }

    public void setInflateExceptionHandler(InflationExceptionHandler inflateExceptionHandler) {
        mInflateExceptionHandler = inflateExceptionHandler;
    public void setInflationCallback(InflationCallback callback) {
        mCallback = callback;
    }

    public interface InflationExceptionHandler {
    public interface InflationCallback {
        void handleInflationException(StatusBarNotification notification, InflationException e);
        void onAsyncInflationFinished(NotificationData.Entry entry);
    }

    public void onDensityOrFontScaleChanged() {
@@ -299,12 +283,67 @@ public class NotificationInflater {
        entry.cachedContentView = null;
        entry.cachedHeadsUpContentView = null;
        entry.cachedPublicContentView = null;
        try {
        inflateNotificationViews();
        } catch (InflationException e) {
            mInflateExceptionHandler.handleInflationException(
                    mRow.getStatusBarNotification(), e);
    }

    private class AsyncInflationTask extends AsyncTask<Void, Void, Notification.Builder> {

        private final StatusBarNotification mSbn;
        private final Context mContext;
        private final int mReInflateFlags;
        private Context mPackageContext = null;
        private Exception mError;

        private AsyncInflationTask(Context context, StatusBarNotification notification,
                int reInflateFlags) {
            mSbn = notification;
            mContext = context;
            mReInflateFlags = reInflateFlags;
            mRow.getEntry().addInflationTask(this);
        }

        @Override
        protected Notification.Builder doInBackground(Void... params) {
            try {
                final Notification.Builder recoveredBuilder
                        = Notification.Builder.recoverBuilder(mContext,
                        mSbn.getNotification());
                mPackageContext = mSbn.getPackageContext(mContext);
                return recoveredBuilder;
            } catch (Exception e) {
                mError = e;
                return null;
            }
        }

        @Override
        protected void onPostExecute(Notification.Builder builder) {
            if (mError == null) {
                finishInflation(mReInflateFlags, builder, mPackageContext);
            } else {
                handleError(mError);
            }
        }
    }

    private void finishInflation(int reinflationFlags, Notification.Builder builder,
            Context context) {
        try {
            inflateNotificationViews(reinflationFlags, builder, context);
        } catch (RuntimeException e){
            handleError(e);
            return;
        }
        mRow.onNotificationUpdated();
        mCallback.onAsyncInflationFinished(mRow.getEntry());
    }

    private void handleError(Exception e) {
        StatusBarNotification sbn = mRow.getStatusBarNotification();
        final String ident = sbn.getPackageName() + "/0x"
                + Integer.toHexString(sbn.getId());
        Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
        mCallback.handleInflationException(sbn,
                new InflationException("Couldn't inflate contentViews" + e));
    }
}
+61 −25
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;

import static com.android.systemui.statusbar.notification.NotificationInflater.InflationExceptionHandler;
import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
@@ -257,7 +257,7 @@ public class StatusBar extends SystemUI implements DemoMode,
        OnHeadsUpChangedListener, VisualStabilityManager.Callback, CommandQueue.Callbacks,
        ActivatableNotificationView.OnActivatedListener,
        ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
        ExpandableNotificationRow.OnExpandClickListener {
        ExpandableNotificationRow.OnExpandClickListener, InflationCallback {
    public static final boolean MULTIUSER_DEBUG = false;

    public static final boolean ENABLE_REMOTE_INPUT =
@@ -713,8 +713,8 @@ public class StatusBar extends SystemUI implements DemoMode,
    private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
    private NotificationIconAreaController mNotificationIconAreaController;
    private ConfigurationListener mConfigurationListener;
    private InflationExceptionHandler mInflationExceptionHandler = this::handleInflationException;
    private boolean mReinflateNotificationsOnUserSwitched;
    private HashMap<String, Entry> mPendingNotifications = new HashMap<>();

    private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
        final int N = array.size();
@@ -1544,29 +1544,24 @@ public class StatusBar extends SystemUI implements DemoMode,
        return new UserHandle(mCurrentUserId);
    }

    public void addNotification(StatusBarNotification notification, RankingMap ranking,
            Entry oldEntry) throws InflationException {
        if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
    public void addNotification(StatusBarNotification notification, RankingMap ranking)
            throws InflationException {
        String key = notification.getKey();
        if (DEBUG) Log.d(TAG, "addNotification key=" + key);

        mNotificationData.updateRanking(ranking);
        Entry shadeEntry = createNotificationViews(notification);
        boolean isHeadsUped = shouldPeek(shadeEntry);
        if (isHeadsUped) {
            mHeadsUpManager.showNotification(shadeEntry);
            // Mark as seen immediately
            setNotificationShown(notification);
        }

        if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
            if (shouldSuppressFullScreenIntent(notification.getKey())) {
            if (shouldSuppressFullScreenIntent(key)) {
                if (DEBUG) {
                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey());
                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + key);
                }
            } else if (mNotificationData.getImportance(notification.getKey())
            } else if (mNotificationData.getImportance(key)
                    < NotificationManager.IMPORTANCE_HIGH) {
                if (DEBUG) {
                    Log.d(TAG, "No Fullscreen intent: not important enough: "
                            + notification.getKey());
                            + key);
                }
            } else {
                // Stop screensaver if the notification has a full-screen intent.
@@ -1578,7 +1573,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                    Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
                try {
                    EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
                            notification.getKey());
                            key);
                    notification.getNotification().fullScreenIntent.send();
                    shadeEntry.notifyFullScreenIntentLaunched();
                    mMetricsLogger.count("note_fullscreen", 1);
@@ -1586,15 +1581,47 @@ public class StatusBar extends SystemUI implements DemoMode,
                }
            }
        }
        addNotificationViews(shadeEntry, ranking);
        abortExistingInflation(key);
        mPendingNotifications.put(key, shadeEntry);
    }

    private void abortExistingInflation(String key) {
        if (mPendingNotifications.containsKey(key)) {
            Entry entry = mPendingNotifications.get(key);
            entry.abortInflation();
            mPendingNotifications.remove(key);
        }
        Entry addedEntry = mNotificationData.get(key);
        if (addedEntry != null) {
            addedEntry.abortInflation();
        }
    }

    private void addEntry(Entry shadeEntry) {
        boolean isHeadsUped = shouldPeek(shadeEntry);
        if (isHeadsUped) {
            mHeadsUpManager.showNotification(shadeEntry);
            // Mark as seen immediately
            setNotificationShown(shadeEntry.notification);
        }
        addNotificationViews(shadeEntry);
        // Recalculate the position of the sliding windows and the titles.
        setAreThereNotifications();
    }

    @Override
    public void handleInflationException(StatusBarNotification notification, InflationException e) {
        handleNotificationError(notification, e.getMessage());
    }

    @Override
    public void onAsyncInflationFinished(Entry entry) {
        mPendingNotifications.remove(entry.key);
        if (mNotificationData.get(entry.key) == null) {
            addEntry(entry);
        }
    }

    private boolean shouldSuppressFullScreenIntent(String key) {
        if (isDeviceInVrMode()) {
            return true;
@@ -1614,6 +1641,7 @@ public class StatusBar extends SystemUI implements DemoMode,

    public void removeNotification(String key, RankingMap ranking) {
        boolean deferRemoval = false;
        abortExistingInflation(key);
        if (mHeadsUpManager.isHeadsUp(key)) {
            // A cancel() in repsonse to a remote input shouldn't be delayed, as it makes the
            // sending look longer than it takes.
@@ -3295,6 +3323,14 @@ public class StatusBar extends SystemUI implements DemoMode,
                    + " scroll " + mStackScroller.getScrollX()
                    + "," + mStackScroller.getScrollY());
        }
        pw.print("  mPendingNotifications=");
        if (mPendingNotifications.size() == 0) {
            pw.println("null");
        } else {
            for (Entry entry : mPendingNotifications.values()) {
                pw.println(entry.notification);
            }
        }

        pw.print("  mInteractingWindows="); pw.println(mInteractingWindows);
        pw.print("  mStatusBarWindowState=");
@@ -5531,7 +5567,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                public void run() {
                    for (StatusBarNotification sbn : notifications) {
                        try {
                            addNotification(sbn, currentRanking, null /* oldEntry */);
                            addNotification(sbn, currentRanking);
                        } catch (InflationException e) {
                            handleInflationException(sbn, e);
                        }
@@ -5574,7 +5610,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                            if (isUpdate) {
                                updateNotification(sbn, rankingMap);
                            } else {
                                addNotification(sbn, rankingMap, null /* oldEntry */);
                                addNotification(sbn, rankingMap);
                            }
                        } catch (InflationException e) {
                            handleInflationException(sbn, e);
@@ -6132,8 +6168,7 @@ public class StatusBar extends SystemUI implements DemoMode,
        }
    }

    protected void inflateViews(Entry entry, ViewGroup parent) throws
            InflationException {
    protected void inflateViews(Entry entry, ViewGroup parent) {
        PackageManager pmUser = getPackageManagerForUser(mContext,
                entry.notification.getUser().getIdentifier());

@@ -6154,7 +6189,7 @@ public class StatusBar extends SystemUI implements DemoMode,
            row.setRemoteInputController(mRemoteInputController);
            row.setOnExpandClickListener(this);
            row.setRemoteViewClickHandler(mOnClickHandler);
            row.setInflateExceptionHandler(mInflationExceptionHandler);
            row.setInflationCallback(this);

            // Get the app name.
            // Note that Notification.Builder#bindHeaderAppName has similar logic
@@ -6552,12 +6587,12 @@ public class StatusBar extends SystemUI implements DemoMode,
        return entry;
    }

    protected void addNotificationViews(Entry entry, RankingMap ranking) {
    protected void addNotificationViews(Entry entry) {
        if (entry == null) {
            return;
        }
        // Add the expanded view and icon.
        mNotificationData.add(entry, ranking);
        mNotificationData.add(entry);
        updateNotifications();
    }

@@ -6675,6 +6710,7 @@ public class StatusBar extends SystemUI implements DemoMode,
        if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");

        final String key = notification.getKey();
        abortExistingInflation(key);
        Entry entry = mNotificationData.get(key);
        if (entry == null) {
            return;
+6 −0
Original line number Diff line number Diff line
@@ -28,4 +28,10 @@ public class Assert {
            throw new IllegalStateException("should be called from the main thread.");
        }
    }

    public static void isNotMainThread() {
        if (Looper.getMainLooper().isCurrentThread()) {
            throw new IllegalStateException("should not be called from the main thread.");
        }
    }
}
Loading