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

Commit f6690100 authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Start processes asynchronously in AMS.

Currently, process start is initiated in ActivityManagerService
holding the main lock and this takes ~40ms to complete. As seen
in some of the issues in previous releases, this is one of the
contributors of the lock contention in system_server. This change
tries to address this issue by moving the process start outside
the locked section.

When a process start is required, instead of doing it synchronously,
this request will be posted on a handler thread. On the handler thread,
this process start request will be completed without holding a lock.
If for some reason, we decide the process is not needed anymore before
it is actually started or being started, then AMS does everything as
usual removing the references to the process from internal state except
actually killing the process which will be handled on the handler
thread.

Bug: 68775202
Test: Ran app startup perf tests using forrest, will update the bug with results.
Test: https://docs.google.com/spreadsheets/d/1cW81guRALZXKsN-WZsKyQiCSY-RgkJ2m_M9IfqIquz8
Test: cts-tradefed run singleCommand cts-dev -m CtsActivityManagerDeviceTestCases
Test: cts-tradefed run singleCommand cts-dev -m CtsWindowManagerDeviceTestCases
Test: cts-tradefed run singleCommand cts-dev -m CtsAppTestCases
Test: cts-tradefed run singleCommand cts-dev -m CtsMultiUserHostTestCases
Test: adb shell am instrument -e package com.android.server.am -w \
      com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
Test: adb shell am instrument -e class com.android.server.pm.UserManagerTest -w \
      com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
Test: adb shell am instrument -e package android.content -w \
      com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
Test: cts-tradefed run singleCommand cts-dev -m CtsProviderTestCases
Test: cts-tradefed run singleCommand cts-dev -m CtsContentTestCases -t \
      android.content.cts.ContentResolverTest
Test: cts-tradefed run singleCommand cts-dev -m CtsContentTestCases -t \
      android.content.cts.ContentProviderTest
Test: cts-tradefed run singleCommand cts-dev -m CtsWebkitTestCases
Test: cts-tradefed run singleCommand cts-dev -m CtsHostsideWebViewTests
Test: cts-tradefed run singleCommand cts-dev -m CtsAssistTestCases
Test: make WebViewLoadingTests && make tradefed-all && tradefed.sh \
      run template/local_min --template:map test=WebViewLoadingTests
Test: adb shell setprop wrap.com.google.android.apps.maps \
      '"LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper"'
      && adb shell dumpsys meminfo --unreachable <PID_OF_APP>
      && check ppid of <APP> is logwrapper's pid.
Test: cts-tradefed run singleCommand cts-dev -m CtsWrapWrapNoDebugTestCases
Test: cts-tradefed run singleCommand cts-dev -m CtsWrapWrapDebugTestCases
Test: cts-tradefed run singleCommand cts-dev -m CtsWrapNoWrapTestCases
Test: cts-tradefed run singleCommand cts-dev -m CtsWrapWrapDebugMallocDebugTestCases
Test: manual

Change-Id: I1fe7ce48cd5a4aadccaf6b3d6fdb5cad3304f1d3
parent 454c831d
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -99,7 +99,10 @@ public abstract class ActivityManagerInternal {
    // Called by the power manager.
    public abstract void onWakefulnessChanged(int wakefulness);

    public abstract int startIsolatedProcess(String entryPoint, String[] mainArgs,
    /**
     * @return {@code true} if process start is successful, {@code false} otherwise.
     */
    public abstract boolean startIsolatedProcess(String entryPoint, String[] mainArgs,
            String processName, String abiOverride, int uid, Runnable crashHandler);

    /**
+21 −4
Original line number Diff line number Diff line
@@ -223,6 +223,12 @@ public final class ActivityThread extends ClientTransactionHandler {
     */
    public static final long INVALID_PROC_STATE_SEQ = -1;

    /**
     * Identifier for the sequence no. associated with this process start. It will be provided
     * as one of the arguments when the process starts.
     */
    public static final String PROC_START_SEQ_IDENT = "seq=";

    private final Object mNetworkPolicyLock = new Object();

    /**
@@ -6274,7 +6280,7 @@ public final class ActivityThread extends ClientTransactionHandler {
        System.exit(0);
    }

    private void attach(boolean system) {
    private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
@@ -6289,7 +6295,7 @@ public final class ActivityThread extends ClientTransactionHandler {
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
@@ -6367,7 +6373,7 @@ public final class ActivityThread extends ClientTransactionHandler {
            ThreadedRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        thread.attach(true, 0);
        return thread;
    }

@@ -6439,8 +6445,19 @@ public final class ActivityThread extends ClientTransactionHandler {

        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
+1 −1
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ interface IActivityManager {
    void unbroadcastIntent(in IApplicationThread caller, in Intent intent, int userId);
    oneway void finishReceiver(in IBinder who, int resultCode, in String resultData, in Bundle map,
            boolean abortBroadcast, int flags);
    void attachApplication(in IApplicationThread app);
    void attachApplication(in IApplicationThread app, long startSeq);
    oneway void activityIdle(in IBinder token, in Configuration config,
            in boolean stopProfiling);
    void activityPaused(in IBinder token);
+1 −0
Original line number Diff line number Diff line
@@ -9463,6 +9463,7 @@ public final class Settings {
         * service_min_restart_time_between     (long)
         * service_max_inactivity               (long)
         * service_bg_start_timeout             (long)
         * process_start_async                  (boolean)
         * </pre>
         *
         * <p>
+5 −4
Original line number Diff line number Diff line
@@ -123,10 +123,11 @@ public class WebViewLibraryLoader {
                throw new IllegalArgumentException(
                        "Native library paths to the WebView RelRo process must not be null!");
            }
            int pid = LocalServices.getService(ActivityManagerInternal.class).startIsolatedProcess(
            boolean success = LocalServices.getService(ActivityManagerInternal.class)
                    .startIsolatedProcess(
                            RelroFileCreator.class.getName(), new String[] { nativeLib.path },
                            "WebViewLoader-" + abi, abi, Process.SHARED_RELRO_UID, crashHandler);
            if (pid <= 0) throw new Exception("Failed to start the relro file creator process");
            if (!success) throw new Exception("Failed to start the relro file creator process");
        } catch (Throwable t) {
            // Log and discard errors as we must not crash the system server.
            Log.e(LOGTAG, "error starting relro file creator for abi " + abi, t);
Loading