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

Commit c22e70f3 authored by Julia Tuttle's avatar Julia Tuttle
Browse files

Inflate notification content on a dedicated thread

We're worried that incoming call notifications might be getting delayed
by other background activity, so we're moving notification content
inflation to a dedicated background thread.

Bug: 308967184
Flag: ACONFIG dedicated_notification_inflation_thread DEVELOPMENT
Test: existing notification tests
Change-Id: I4f6331bf3ae21ae5871a6f16f6235af2412950c5
parent ad722bac
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -519,3 +519,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "dedicated_notif_inflation_thread"
    namespace: "systemui"
    description: "Create a separate background thread for inflating notifications"
    bug: "308967184"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.dagger.qualifiers

import javax.inject.Qualifier

@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class NotifInflation
+23 −25
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ import android.widget.RemoteViews;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.ImageMessageConsumer;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.NotifInflation;
import com.android.systemui.media.controls.util.MediaFeatureFlag;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.InflationTask;
@@ -82,7 +82,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
    private final NotificationRemoteInputManager mRemoteInputManager;
    private final NotifRemoteViewCache mRemoteViewCache;
    private final ConversationNotificationProcessor mConversationProcessor;
    private final Executor mBgExecutor;
    private final Executor mInflationExecutor;
    private final SmartReplyStateInflater mSmartReplyStateInflater;
    private final NotifLayoutInflaterFactory.Provider mNotifLayoutInflaterFactoryProvider;
    private final NotificationContentInflaterLogger mLogger;
@@ -93,7 +93,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
            NotificationRemoteInputManager remoteInputManager,
            ConversationNotificationProcessor conversationProcessor,
            MediaFeatureFlag mediaFeatureFlag,
            @Background Executor bgExecutor,
            @NotifInflation Executor inflationExecutor,
            SmartReplyStateInflater smartRepliesInflater,
            NotifLayoutInflaterFactory.Provider notifLayoutInflaterFactoryProvider,
            NotificationContentInflaterLogger logger) {
@@ -101,7 +101,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
        mRemoteInputManager = remoteInputManager;
        mConversationProcessor = conversationProcessor;
        mIsMediaInQS = mediaFeatureFlag.getEnabled();
        mBgExecutor = bgExecutor;
        mInflationExecutor = inflationExecutor;
        mSmartReplyStateInflater = smartRepliesInflater;
        mNotifLayoutInflaterFactoryProvider = notifLayoutInflaterFactoryProvider;
        mLogger = logger;
@@ -138,7 +138,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
        cancelContentViewFrees(row, contentToBind);

        AsyncInflationTask task = new AsyncInflationTask(
                mBgExecutor,
                mInflationExecutor,
                mInflateSynchronously,
                /* reInflateFlags = */ contentToBind,
                mRemoteViewCache,
@@ -157,7 +157,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
        if (mInflateSynchronously) {
            task.onPostExecute(task.doInBackground());
        } else {
            task.executeOnExecutor(mBgExecutor);
            task.executeOnExecutor(mInflationExecutor);
        }
    }

@@ -208,7 +208,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
        }

        apply(
                mBgExecutor,
                mInflationExecutor,
                inflateSynchronously,
                result,
                reInflateFlags,
@@ -416,7 +416,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
    }

    private static CancellationSignal apply(
            Executor bgExecutor,
            Executor inflationExecutor,
            boolean inflateSynchronously,
            InflationProgress result,
            @InflationFlag int reInflateFlags,
@@ -447,7 +447,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
                }
            };
            logger.logAsyncTaskProgress(entry, "applying contracted view");
            applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
            applyRemoteView(inflationExecutor, inflateSynchronously, result, reInflateFlags, flag,
                    remoteViewCache, entry, row, isNewView, remoteViewClickHandler, callback,
                    privateLayout, privateLayout.getContractedChild(),
                    privateLayout.getVisibleWrapper(
@@ -474,11 +474,10 @@ public class NotificationContentInflater implements NotificationRowContentBinder
                    }
                };
                logger.logAsyncTaskProgress(entry, "applying expanded view");
                applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
                        remoteViewCache, entry, row, isNewView, remoteViewClickHandler,
                applyRemoteView(inflationExecutor, inflateSynchronously, result, reInflateFlags,
                        flag, remoteViewCache, entry, row, isNewView, remoteViewClickHandler,
                        callback, privateLayout, privateLayout.getExpandedChild(),
                        privateLayout.getVisibleWrapper(
                                NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations,
                        privateLayout.getVisibleWrapper(VISIBLE_TYPE_EXPANDED), runningInflations,
                        applyCallback, logger);
            }
        }
@@ -502,11 +501,10 @@ public class NotificationContentInflater implements NotificationRowContentBinder
                    }
                };
                logger.logAsyncTaskProgress(entry, "applying heads up view");
                applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
                        remoteViewCache, entry, row, isNewView, remoteViewClickHandler,
                applyRemoteView(inflationExecutor, inflateSynchronously, result, reInflateFlags,
                        flag, remoteViewCache, entry, row, isNewView, remoteViewClickHandler,
                        callback, privateLayout, privateLayout.getHeadsUpChild(),
                        privateLayout.getVisibleWrapper(
                                VISIBLE_TYPE_HEADSUP), runningInflations,
                        privateLayout.getVisibleWrapper(VISIBLE_TYPE_HEADSUP), runningInflations,
                        applyCallback, logger);
            }
        }
@@ -529,7 +527,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
                }
            };
            logger.logAsyncTaskProgress(entry, "applying public view");
            applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
            applyRemoteView(inflationExecutor, inflateSynchronously, result, reInflateFlags, flag,
                    remoteViewCache, entry, row, isNewView, remoteViewClickHandler, callback,
                    publicLayout, publicLayout.getContractedChild(),
                    publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED),
@@ -551,7 +549,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder

    @VisibleForTesting
    static void applyRemoteView(
            Executor bgExecutor,
            Executor inflationExecutor,
            boolean inflateSynchronously,
            final InflationProgress result,
            final @InflationFlag int reInflateFlags,
@@ -655,14 +653,14 @@ public class NotificationContentInflater implements NotificationRowContentBinder
            cancellationSignal = newContentView.applyAsync(
                    result.packageContext,
                    parentLayout,
                    bgExecutor,
                    inflationExecutor,
                    listener,
                    remoteViewClickHandler);
        } else {
            cancellationSignal = newContentView.reapplyAsync(
                    result.packageContext,
                    existingView,
                    bgExecutor,
                    inflationExecutor,
                    listener,
                    remoteViewClickHandler);
        }
@@ -918,7 +916,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
        private final boolean mUsesIncreasedHeadsUpHeight;
        private final @InflationFlag int mReInflateFlags;
        private final NotifRemoteViewCache mRemoteViewCache;
        private final Executor mBgExecutor;
        private final Executor mInflationExecutor;
        private ExpandableNotificationRow mRow;
        private Exception mError;
        private RemoteViews.InteractionHandler mRemoteViewClickHandler;
@@ -930,7 +928,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
        private final NotificationContentInflaterLogger mLogger;

        private AsyncInflationTask(
                Executor bgExecutor,
                Executor inflationExecutor,
                boolean inflateSynchronously,
                @InflationFlag int reInflateFlags,
                NotifRemoteViewCache cache,
@@ -948,7 +946,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
                NotificationContentInflaterLogger logger) {
            mEntry = entry;
            mRow = row;
            mBgExecutor = bgExecutor;
            mInflationExecutor = inflationExecutor;
            mInflateSynchronously = inflateSynchronously;
            mReInflateFlags = reInflateFlags;
            mRemoteViewCache = cache;
@@ -1067,7 +1065,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
            if (mError == null) {
                // Logged in detail in apply.
                mCancellationSignal = apply(
                        mBgExecutor,
                        mInflationExecutor,
                        mInflateSynchronously,
                        result,
                        mReInflateFlags,
+30 −0
Original line number Diff line number Diff line
@@ -23,11 +23,13 @@ import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;

import com.android.systemui.Flags;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.BroadcastRunning;
import com.android.systemui.dagger.qualifiers.LongRunning;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.NotifInflation;

import dagger.Module;
import dagger.Provides;
@@ -50,6 +52,8 @@ public abstract class SysUIConcurrencyModule {
    private static final Long LONG_SLOW_DELIVERY_THRESHOLD = 2500L;
    private static final Long BROADCAST_SLOW_DISPATCH_THRESHOLD = 1000L;
    private static final Long BROADCAST_SLOW_DELIVERY_THRESHOLD = 1000L;
    private static final Long NOTIFICATION_INFLATION_SLOW_DISPATCH_THRESHOLD = 1000L;
    private static final Long NOTIFICATION_INFLATION_SLOW_DELIVERY_THRESHOLD = 1000L;

    /** Background Looper */
    @Provides
@@ -90,6 +94,24 @@ public abstract class SysUIConcurrencyModule {
        return thread.getLooper();
    }

    /** Notification inflation Looper */
    @Provides
    @SysUISingleton
    @NotifInflation
    public static Looper provideNotifInflationLooper(@Background Looper bgLooper) {
        if (!Flags.dedicatedNotifInflationThread()) {
            return bgLooper;
        }

        final HandlerThread thread = new HandlerThread("NotifInflation",
                Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();
        final Looper looper = thread.getLooper();
        looper.setSlowLogThresholdMs(NOTIFICATION_INFLATION_SLOW_DISPATCH_THRESHOLD,
                NOTIFICATION_INFLATION_SLOW_DELIVERY_THRESHOLD);
        return looper;
    }

    /**
     * Background Handler.
     *
@@ -225,4 +247,12 @@ public abstract class SysUIConcurrencyModule {
        thread.start();
        return new Handler(thread.getLooper());
    }

    /** */
    @Provides
    @SysUISingleton
    @NotifInflation
    public static Executor provideNotifInflationExecutor(@NotifInflation Looper looper) {
        return new ExecutorImpl(looper);
    }
}