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

Commit 7d21811b authored by Kai Li's avatar Kai Li
Browse files

Warm up Content Capture's BackgroundThread in ActivityThread.

So that BackgroundThread's state will be initiated in the application start up time, instead of the activity start up time. This may reduce the ANR.

Change-Id: I23b99deb03735b2fb6be5d610d27e5f283f609c0
Bug: 408273598
Flag: android.view.contentcapture.flags.warm_up_background_thread_for_content_capture
Test: atest FrameworksCoreTests:android.view.contentcapture.MainContentCaptureSessionTest
parent 98424bf3
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.ApplicationSharedMemory;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.DebugStore;
@@ -7794,6 +7795,16 @@ public final class ActivityThread extends ClientTransactionHandler

            // Propagate Content Capture options
            app.setContentCaptureOptions(data.contentCaptureOptions);
            if (android.view.contentcapture.flags.Flags.warmUpBackgroundThreadForContentCapture()
                    && data.contentCaptureOptions != null) {
                if (data.contentCaptureOptions.enableReceiver
                        && !data.contentCaptureOptions.lite) {
                    // Warm up the background thread when:
                    // 1) app is launched with content capture enabled, and
                    // 2) the app is NOT launched with content capture lite enabled.
                    BackgroundThread.startIfNeeded();
                }
            }
            sendMessage(H.SET_CONTENT_CAPTURE_OPTIONS_CALLBACK, data.appInfo.packageName);

            mInitialApplication = app;
+10 −0
Original line number Diff line number Diff line
@@ -27,3 +27,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "warm_up_background_thread_for_content_capture"
    namespace: "system_performance"
    description: "Feature flag to warm up the background thread for content capture"
    bug: "408273598"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+20 −4
Original line number Diff line number Diff line
@@ -40,10 +40,17 @@ public final class BackgroundThread extends HandlerThread {
        super("android.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
    }

    private static void ensureThreadLocked() {
    private static void ensureThreadStartedLocked() {
        if (sInstance == null) {
            sInstance = new BackgroundThread();
            sInstance.start();
        }
    }

    private static void ensureThreadReadyLocked() {
        ensureThreadStartedLocked();
        if (sHandler == null) {
            // This will block until the looper is initialized on the background thread.
            final Looper looper = sInstance.getLooper();
            looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
            looper.setSlowLogThresholdMs(
@@ -54,10 +61,19 @@ public final class BackgroundThread extends HandlerThread {
        }
    }

    /**
     * Starts the thread if needed, but doesn't block on thread initialization or readiness.
     */
    public static void startIfNeeded() {
        synchronized (BackgroundThread.class) {
            ensureThreadStartedLocked();
        }
    }

    @NonNull
    public static BackgroundThread get() {
        synchronized (BackgroundThread.class) {
            ensureThreadLocked();
            ensureThreadReadyLocked();
            return sInstance;
        }
    }
@@ -65,7 +81,7 @@ public final class BackgroundThread extends HandlerThread {
    @NonNull
    public static Handler getHandler() {
        synchronized (BackgroundThread.class) {
            ensureThreadLocked();
            ensureThreadReadyLocked();
            return sHandler;
        }
    }
@@ -73,7 +89,7 @@ public final class BackgroundThread extends HandlerThread {
    @NonNull
    public static Executor getExecutor() {
        synchronized (BackgroundThread.class) {
            ensureThreadLocked();
            ensureThreadReadyLocked();
            return sHandlerExecutor;
        }
    }
+18 −0
Original line number Diff line number Diff line
@@ -51,4 +51,22 @@ public class BackgroundThreadTest {
        boolean success = done.block(5000);
        assertThat(success).isTrue();
    }

    @Test
    public void test_startIfNeeded() {
        BackgroundThread.startIfNeeded();

        BackgroundThread thread = BackgroundThread.get();
        assertThat(thread.getLooper()).isNotEqualTo(Looper.getMainLooper());
    }

    @Test
    public void test_startIfNeededMultipleTimes() {
        BackgroundThread.startIfNeeded();
        BackgroundThread.startIfNeeded();
        BackgroundThread.startIfNeeded();

        BackgroundThread thread = BackgroundThread.get();
        assertThat(thread.getLooper()).isNotEqualTo(Looper.getMainLooper());
    }
}