Merge "Adds Zygote policy flags to control how applications are launched"
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 1c0f0f4..994ed21 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -487,6 +487,40 @@
     private static long sStartUptimeMillis;
 
     /**
+     * Value used to indicate that there is no special information about an application launch.  App
+     * launches with this policy will occur through the primary or secondary Zygote with no special
+     * treatment.
+     *
+     * @hide
+     */
+    public static final int ZYGOTE_POLICY_FLAG_EMPTY = 0;
+
+    /**
+     * Flag used to indicate that an application launch is user-visible and latency sensitive.  Any
+     * launch with this policy will use a Unspecialized App Process Pool if the target Zygote
+     * supports it.
+     *
+     * @hide
+     */
+    public static final int ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE = 1 << 0;
+
+    /**
+     * Flag used to indicate that the launch is one in a series of app launches that will be
+     * performed in quick succession.  For future use.
+     *
+     * @hide
+     */
+    public static final int ZYGOTE_POLICY_FLAG_BATCH_LAUNCH = 1 << 1;
+
+    /**
+     * Flag used to indicate that the current launch event is for a system process.  All system
+     * processes are equally important, so none of them should be prioritized over the others.
+     *
+     * @hide
+     */
+    public static final int ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS = 1 << 2;
+
+    /**
      * State associated with the zygote process.
      * @hide
      */
@@ -525,6 +559,7 @@
      * @param appDataDir null-ok the data directory of the app.
      * @param invokeWith null-ok the command to invoke with.
      * @param packageName null-ok the name of the package this process belongs to.
+     * @param zygotePolicyFlags Flags used to determine how to launch the application
      * @param isTopApp whether the process starts for high priority application.
      * @param disabledCompatChanges null-ok list of disabled compat changes for the process being
      *                             started.
@@ -546,13 +581,14 @@
                                            @Nullable String appDataDir,
                                            @Nullable String invokeWith,
                                            @Nullable String packageName,
+                                           int zygotePolicyFlags,
                                            boolean isTopApp,
                                            @Nullable long[] disabledCompatChanges,
                                            @Nullable String[] zygoteArgs) {
         return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
-                    /*useUsapPool=*/ true, isTopApp, disabledCompatChanges, zygoteArgs);
+                    zygotePolicyFlags, isTopApp, disabledCompatChanges, zygoteArgs);
     }
 
     /** @hide */
@@ -573,7 +609,8 @@
         return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
-                    /*useUsapPool=*/ false, /*isTopApp=*/ false, disabledCompatChanges, zygoteArgs);
+                    /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false,
+                    disabledCompatChanges, zygoteArgs);
     }
 
     /**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 32df052..6334e7b 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import static android.os.Process.ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE;
+import static android.os.Process.ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -117,6 +120,10 @@
         mUsapPoolSecondarySocketAddress =
                 new LocalSocketAddress(Zygote.USAP_POOL_SECONDARY_SOCKET_NAME,
                                        LocalSocketAddress.Namespace.RESERVED);
+
+        // This constructor is used to create the primary and secondary Zygotes, which can support
+        // Unspecialized App Process Pools.
+        mUsapPoolSupported = true;
     }
 
     public ZygoteProcess(LocalSocketAddress primarySocketAddress,
@@ -126,6 +133,10 @@
 
         mUsapPoolSocketAddress = null;
         mUsapPoolSecondarySocketAddress = null;
+
+        // This constructor is used to create the primary and secondary Zygotes, which CAN NOT
+        // support Unspecialized App Process Pools.
+        mUsapPoolSupported = false;
     }
 
     public LocalSocketAddress getPrimarySocketAddress() {
@@ -265,6 +276,14 @@
     private ZygoteState secondaryZygoteState;
 
     /**
+     * If this Zygote supports the creation and maintenance of a USAP pool.
+     *
+     * Currently only the primary and secondary Zygotes support USAP pools. Any
+     * child Zygotes will be unable to create or use a USAP pool.
+     */
+    private final boolean mUsapPoolSupported;
+
+    /**
      * If the USAP pool should be created and used to start applications.
      *
      * Setting this value to false will disable the creation, maintenance, and use of the USAP
@@ -306,11 +325,11 @@
      * @param appDataDir null-ok the data directory of the app.
      * @param invokeWith null-ok the command to invoke with.
      * @param packageName null-ok the name of the package this process belongs to.
+     * @param zygotePolicyFlags Flags used to determine how to launch the application.
+     * @param isTopApp Whether the process starts for high priority application.
      * @param disabledCompatChanges null-ok list of disabled compat changes for the process being
      *                             started.
-     * @param zygoteArgs Additional arguments to supply to the zygote process.
-     * @param isTopApp Whether the process starts for high priority application.
-     *
+     * @param zygoteArgs Additional arguments to supply to the Zygote process.
      * @return An object that describes the result of the attempt to start the process.
      * @throws RuntimeException on fatal start failure
      */
@@ -325,7 +344,7 @@
                                                   @Nullable String appDataDir,
                                                   @Nullable String invokeWith,
                                                   @Nullable String packageName,
-                                                  boolean useUsapPool,
+                                                  int zygotePolicyFlags,
                                                   boolean isTopApp,
                                                   @Nullable long[] disabledCompatChanges,
                                                   @Nullable String[] zygoteArgs) {
@@ -338,7 +357,7 @@
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
-                    packageName, useUsapPool, isTopApp, disabledCompatChanges, zygoteArgs);
+                    packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -384,7 +403,7 @@
      */
     @GuardedBy("mLock")
     private Process.ProcessStartResult zygoteSendArgsAndGetResult(
-            ZygoteState zygoteState, boolean useUsapPool, @NonNull ArrayList<String> args)
+            ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
             throws ZygoteStartFailedEx {
         // Throw early if any of the arguments are malformed. This means we can
         // avoid writing a partial response to the zygote.
@@ -410,7 +429,7 @@
          */
         String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";
 
-        if (useUsapPool && mUsapPoolEnabled && canAttemptUsap(args)) {
+        if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {
             try {
                 return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);
             } catch (IOException ex) {
@@ -481,7 +500,43 @@
     }
 
     /**
-     * Flags that may not be passed to a USAP.
+     * Test various member properties and parameters to determine if a launch event should be
+     * handled using an Unspecialized App Process Pool or not.
+     *
+     * @param zygotePolicyFlags Policy flags indicating special behavioral observations about the
+     *                          Zygote command
+     * @param args Arguments that will be passed to the Zygote
+     * @return If the command should be sent to a USAP Pool member or an actual Zygote
+     */
+    private boolean shouldAttemptUsapLaunch(int zygotePolicyFlags, ArrayList<String> args) {
+        return mUsapPoolSupported
+                && mUsapPoolEnabled
+                && policySpecifiesUsapPoolLaunch(zygotePolicyFlags)
+                && commandSupportedByUsap(args);
+    }
+
+    /**
+     * Tests a Zygote policy flag set for various properties that determine if it is eligible for
+     * being handled by an Unspecialized App Process Pool.
+     *
+     * @param zygotePolicyFlags Policy flags indicating special behavioral observations about the
+     *                          Zygote command
+     * @return If the policy allows for use of a USAP pool
+     */
+    private static boolean policySpecifiesUsapPoolLaunch(int zygotePolicyFlags) {
+        /*
+         * Zygote USAP Pool Policy: Launch the new process from the USAP Pool iff the launch event
+         * is latency sensitive but *NOT* a system process.  All system processes are equally
+         * important so we don't want to prioritize one over another.
+         */
+        return (zygotePolicyFlags
+                & (ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS | ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE))
+                == ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE;
+    }
+
+    /**
+     * Flags that may not be passed to a USAP.  These may appear as prefixes to individual Zygote
+     * arguments.
      */
     private static final String[] INVALID_USAP_FLAGS = {
         "--query-abi-list",
@@ -498,10 +553,11 @@
 
     /**
      * Tests a command list to see if it is valid to send to a USAP.
+     *
      * @param args  Zygote/USAP command arguments
      * @return  True if the command can be passed to a USAP; false otherwise
      */
-    private static boolean canAttemptUsap(ArrayList<String> args) {
+    private static boolean commandSupportedByUsap(ArrayList<String> args) {
         for (String flag : args) {
             for (String badFlag : INVALID_USAP_FLAGS) {
                 if (flag.startsWith(badFlag)) {
@@ -539,6 +595,7 @@
      * @param startChildZygote Start a sub-zygote. This creates a new zygote process
      * that has its state cloned from this zygote process.
      * @param packageName null-ok the name of the package this process belongs to.
+     * @param zygotePolicyFlags Flags used to determine how to launch the application.
      * @param isTopApp Whether the process starts for high priority application.
      * @param disabledCompatChanges a list of disabled compat changes for the process being started.
      * @param extraArgs Additional arguments to supply to the zygote process.
@@ -558,7 +615,7 @@
                                                       @Nullable String invokeWith,
                                                       boolean startChildZygote,
                                                       @Nullable String packageName,
-                                                      boolean useUsapPool,
+                                                      int zygotePolicyFlags,
                                                       boolean isTopApp,
                                                       @Nullable long[] disabledCompatChanges,
                                                       @Nullable String[] extraArgs)
@@ -661,7 +718,7 @@
             // The USAP pool can not be used if the application will not use the systems graphics
             // driver.  If that driver is requested use the Zygote application start path.
             return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
-                                              useUsapPool,
+                                              zygotePolicyFlags,
                                               argsForZygote);
         }
     }
@@ -691,6 +748,10 @@
     private long mLastPropCheckTimestamp = 0;
 
     private boolean fetchUsapPoolEnabledPropWithMinInterval() {
+        // If this Zygote doesn't support USAPs there is no need to fetch any
+        // properties.
+        if (!mUsapPoolSupported) return false;
+
         final long currentTimestamp = SystemClock.elapsedRealtime();
 
         if (SystemProperties.get("dalvik.vm.boot-image", "").endsWith("apex.art")) {
@@ -1198,7 +1259,7 @@
                     gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
                     abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
                     true /* startChildZygote */, null /* packageName */,
-                    false /* useUsapPool */, false /* isTopApp */,
+                    ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
                     null /* disabledCompatChanges */, extraArgs);
         } catch (ZygoteStartFailedEx ex) {
             throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 5833d16..0ba4173 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;
+import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
@@ -2616,8 +2617,10 @@
         // Not running -- get it started, and enqueue this service record
         // to be executed when the app comes up.
         if (app == null && !permissionsReviewRequired) {
+            // TODO (chriswailes): Change the Zygote policy flags based on if the launch-for-service
+            //  was initiated from a notification tap or not.
             if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
-                    hostingRecord, false, isolated, false)) == null) {
+                    hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {
                 String msg = "Unable to launch app "
                         + r.appInfo.packageName + "/"
                         + r.appInfo.uid + " for service "
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b0e476a..9678abb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -67,6 +67,10 @@
 import static android.os.Process.SIGNAL_USR1;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
+import static android.os.Process.ZYGOTE_POLICY_FLAG_BATCH_LAUNCH;
+import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
+import static android.os.Process.ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE;
+import static android.os.Process.ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS;
 import static android.os.Process.ZYGOTE_PROCESS;
 import static android.os.Process.getTotalMemory;
 import static android.os.Process.isThreadInProcess;
@@ -3033,7 +3037,7 @@
             info.targetSdkVersion = Build.VERSION.SDK_INT;
             ProcessRecord proc = mProcessList.startProcessLocked(processName, info /* info */,
                     false /* knownToBeDead */, 0 /* intentFlags */,
-                    sNullHostingRecord  /* hostingRecord */,
+                    sNullHostingRecord  /* hostingRecord */, ZYGOTE_POLICY_FLAG_EMPTY,
                     true /* allowWhileBooting */, true /* isolated */,
                     uid, true /* keepIfLarge */, abiOverride, entryPoint, entryPointArgs,
                     crashHandler);
@@ -3044,12 +3048,12 @@
     @GuardedBy("this")
     final ProcessRecord startProcessLocked(String processName,
             ApplicationInfo info, boolean knownToBeDead, int intentFlags,
-            HostingRecord hostingRecord, boolean allowWhileBooting,
+            HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
             boolean isolated, boolean keepIfLarge) {
         return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
-                hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
-                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
-                null /* crashHandler */);
+                hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
+                keepIfLarge, null /* ABI override */, null /* entryPoint */,
+                null /* entryPointArgs */, null /* crashHandler */);
     }
 
     boolean isAllowedWhileBooting(ApplicationInfo ai) {
@@ -4868,7 +4872,8 @@
         } catch (RemoteException e) {
             app.resetPackageList(mProcessStats);
             mProcessList.startProcessLocked(app,
-                    new HostingRecord("link fail", processName));
+                    new HostingRecord("link fail", processName),
+                    ZYGOTE_POLICY_FLAG_EMPTY);
             return false;
         }
 
@@ -5114,7 +5119,8 @@
 
             app.resetPackageList(mProcessStats);
             app.unlinkDeathRecipient();
-            mProcessList.startProcessLocked(app, new HostingRecord("bind-fail", processName));
+            mProcessList.startProcessLocked(app, new HostingRecord("bind-fail", processName),
+                    ZYGOTE_POLICY_FLAG_EMPTY);
             return false;
         }
 
@@ -5313,7 +5319,9 @@
                 for (int ip=0; ip<NP; ip++) {
                     if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "Starting process on hold: "
                             + procs.get(ip));
-                    mProcessList.startProcessLocked(procs.get(ip), new HostingRecord("on-hold"));
+                    mProcessList.startProcessLocked(procs.get(ip),
+                            new HostingRecord("on-hold"),
+                            ZYGOTE_POLICY_FLAG_BATCH_LAUNCH);
                 }
             }
             if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
@@ -7094,8 +7102,9 @@
                             proc = startProcessLocked(cpi.processName,
                                     cpr.appInfo, false, 0,
                                     new HostingRecord("content provider",
-                                    new ComponentName(cpi.applicationInfo.packageName,
-                                            cpi.name)), false, false, false);
+                                        new ComponentName(cpi.applicationInfo.packageName,
+                                                cpi.name)),
+                                    ZYGOTE_POLICY_FLAG_EMPTY, false, false, false);
                             checkTime(startTime, "getContentProviderImpl: after start process");
                             if (proc == null) {
                                 Slog.w(TAG, "Unable to launch app "
@@ -7622,7 +7631,8 @@
                         .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
                 for (ApplicationInfo app : apps) {
                     if (!"android".equals(app.packageName)) {
-                        addAppLocked(app, null, false, null /* ABI override */);
+                        addAppLocked(app, null, false, null /* ABI override */,
+                                ZYGOTE_POLICY_FLAG_BATCH_LAUNCH);
                     }
                 }
             } catch (RemoteException ex) {
@@ -7805,23 +7815,25 @@
 
     @GuardedBy("this")
     final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
-            String abiOverride) {
+            String abiOverride, int zygotePolicyFlags) {
         return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */,
-                false /* mountExtStorageFull */, abiOverride);
+                false /* mountExtStorageFull */, abiOverride, zygotePolicyFlags);
     }
 
     @GuardedBy("this")
     final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
-            boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) {
+            boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride,
+            int zygotePolicyFlags) {
         return addAppLocked(info, customProcess, isolated, disableHiddenApiChecks,
-                false /* disableTestApiChecks */, mountExtStorageFull, abiOverride);
+                false /* disableTestApiChecks */, mountExtStorageFull, abiOverride,
+                zygotePolicyFlags);
     }
 
     // TODO: Move to ProcessList?
     @GuardedBy("this")
     final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
             boolean disableHiddenApiChecks, boolean disableTestApiChecks,
-            boolean mountExtStorageFull, String abiOverride) {
+            boolean mountExtStorageFull, String abiOverride, int zygotePolicyFlags) {
         ProcessRecord app;
         if (!isolated) {
             app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -7856,7 +7868,8 @@
             mPersistentStartingProcesses.add(app);
             mProcessList.startProcessLocked(app, new HostingRecord("added application",
                     customProcess != null ? customProcess : app.processName),
-                    disableHiddenApiChecks, disableTestApiChecks, mountExtStorageFull, abiOverride);
+                    zygotePolicyFlags, disableHiddenApiChecks, disableTestApiChecks,
+                    mountExtStorageFull, abiOverride);
         }
 
         return app;
@@ -13892,7 +13905,8 @@
             mProcessList.addProcessNameLocked(app);
             app.pendingStart = false;
             mProcessList.startProcessLocked(app,
-                    new HostingRecord("restart", app.processName));
+                    new HostingRecord("restart", app.processName),
+                    ZYGOTE_POLICY_FLAG_EMPTY);
             return true;
         } else if (app.pid > 0 && app.pid != MY_PID) {
             // Goodbye!
@@ -14250,7 +14264,7 @@
             ProcessRecord proc = startProcessLocked(app.processName, app,
                     false, 0,
                     new HostingRecord("backup", hostingName),
-                    false, false, false);
+                    ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS, false, false, false);
             if (proc == null) {
                 Slog.e(TAG, "Unable to start backup agent process " + r);
                 return false;
@@ -15866,7 +15880,8 @@
             }
 
             ProcessRecord app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
-                    disableTestApiChecks, mountExtStorageFull, abiOverride);
+                    disableTestApiChecks, mountExtStorageFull, abiOverride,
+                    ZYGOTE_POLICY_FLAG_EMPTY);
             app.setActiveInstrumentation(activeInstr);
             activeInstr.mFinished = false;
             activeInstr.mRunningProcesses.add(app);
@@ -17342,7 +17357,8 @@
                 mProcessList.mRemovedProcesses.remove(i);
 
                 if (app.isPersistent()) {
-                    addAppLocked(app.info, null, false, null /* ABI override */);
+                    addAppLocked(app.info, null, false, null /* ABI override */,
+                            ZYGOTE_POLICY_FLAG_BATCH_LAUNCH);
                 }
             }
         }
@@ -18486,8 +18502,8 @@
                     // preempted by other processes before attaching the process of top app.
                     startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                             new HostingRecord(hostingType, hostingName, isTop),
-                            false /* allowWhileBooting */, false /* isolated */,
-                            true /* keepIfLarge */);
+                            ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
+                            false /* isolated */, true /* keepIfLarge */);
                 }
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index e6c9e800..6938d11 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -16,6 +16,9 @@
 
 package com.android.server.am;
 
+import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
+import static android.os.Process.ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE;
+
 import static com.android.server.am.ActivityManagerDebugConfig.*;
 
 import android.app.ActivityManager;
@@ -1588,7 +1591,9 @@
                     + receiverUid);
         }
 
-        if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
+        final boolean isActivityCapable =
+                (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0);
+        if (isActivityCapable) {
             scheduleTempWhitelistLocked(receiverUid,
                     brOptions.getTemporaryAppWhitelistDuration(), r);
         }
@@ -1643,6 +1648,7 @@
                 info.activityInfo.applicationInfo, true,
                 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                 new HostingRecord("broadcast", r.curComponent),
+                isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
                 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                         == null) {
             // Ah, this recipient is unavailable.  Finish it if necessary,
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3996ae2..d935162 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -23,6 +23,7 @@
 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
 import static android.os.Process.getFreeMemory;
 import static android.os.Process.getTotalMemory;
 import static android.os.Process.killProcessQuiet;
@@ -1506,7 +1507,7 @@
      */
     @GuardedBy("mService")
     boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
-            boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+            int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
             boolean mountExtStorageFull, String abiOverride) {
         if (app.pendingStart) {
             return true;
@@ -1600,8 +1601,7 @@
             }
             // Run the app in safe mode if its manifest requests so or the
             // system is booted in safe mode.
-            if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
-                    mService.mSafeMode == true) {
+            if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || mService.mSafeMode) {
                 runtimeFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
             }
             if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL) != 0) {
@@ -1710,8 +1710,8 @@
             final String entryPoint = "android.app.ActivityThread";
 
             return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
-                    runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
-                    startTime);
+                    runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
+                    instructionSet, invokeWith, startTime);
         } catch (RuntimeException e) {
             Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e);
 
@@ -1728,9 +1728,8 @@
     }
 
     @GuardedBy("mService")
-    boolean startProcessLocked(HostingRecord hostingRecord,
-            String entryPoint,
-            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
+    boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
+            int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
             String seInfo, String requiredAbi, String instructionSet, String invokeWith,
             long startTime) {
         app.pendingStart = true;
@@ -1761,8 +1760,9 @@
             mService.mProcStartHandler.post(() -> {
                 try {
                     final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
-                            entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,
-                            app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime);
+                            entryPoint, app, app.startUid, gids, runtimeFlags, zygotePolicyFlags,
+                            mountExternal, app.seInfo, requiredAbi, instructionSet, invokeWith,
+                            app.startTime);
                     synchronized (mService) {
                         handleProcessStartedLocked(app, startResult, startSeq);
                     }
@@ -1783,8 +1783,8 @@
             try {
                 final Process.ProcessStartResult startResult = startProcess(hostingRecord,
                         entryPoint, app,
-                        uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
-                        invokeWith, startTime);
+                        uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
+                        requiredAbi, instructionSet, invokeWith, startTime);
                 handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                         startSeq, false);
             } catch (RuntimeException e) {
@@ -1891,9 +1891,9 @@
     }
 
     private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
-            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
-            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
-            long startTime) {
+            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
+            int mountExternal, String seInfo, String requiredAbi, String instructionSet,
+            String invokeWith, long startTime) {
         try {
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                     app.processName);
@@ -1920,14 +1920,15 @@
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, app.info.packageName,
-                        /*useUsapPool=*/ false, isTopApp, app.mDisabledCompatChanges,
+                        /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
+                        app.mDisabledCompatChanges,
                         new String[]{PROC_START_SEQ_IDENT + app.startSeq});
             } else {
                 startResult = Process.start(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
-                        app.info.dataDir, invokeWith, app.info.packageName, isTopApp,
-                        app.mDisabledCompatChanges,
+                        app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
+                        isTopApp, app.mDisabledCompatChanges,
                         new String[]{PROC_START_SEQ_IDENT + app.startSeq});
             }
             checkSlow(startTime, "startProcess: returned from zygote!");
@@ -1938,14 +1939,14 @@
     }
 
     @GuardedBy("mService")
-    final void startProcessLocked(ProcessRecord app, HostingRecord hostingRecord) {
-        startProcessLocked(app, hostingRecord, null /* abiOverride */);
+    void startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, int zygotePolicyFlags) {
+        startProcessLocked(app, hostingRecord, zygotePolicyFlags, null /* abiOverride */);
     }
 
     @GuardedBy("mService")
     final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
-            String abiOverride) {
-        return startProcessLocked(app, hostingRecord,
+            int zygotePolicyFlags, String abiOverride) {
+        return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
                 false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
                 false /* mountExtStorageFull */, abiOverride);
     }
@@ -1953,8 +1954,9 @@
     @GuardedBy("mService")
     final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
             boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
-            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
-            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
+            int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
+            boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
+            Runnable crashHandler) {
         long startTime = SystemClock.elapsedRealtime();
         ProcessRecord app;
         if (!isolated) {
@@ -2055,7 +2057,8 @@
         }
 
         checkSlow(startTime, "startProcess: stepping in to startProcess");
-        final boolean success = startProcessLocked(app, hostingRecord, abiOverride);
+        final boolean success =
+                startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
         checkSlow(startTime, "startProcess: done starting proc!");
         return success ? app : null;
     }
@@ -2363,7 +2366,8 @@
             mService.handleAppDiedLocked(app, willRestart, allowRestart);
             if (willRestart) {
                 removeLruProcessLocked(app);
-                mService.addAppLocked(app.info, null, false, null /* ABI override */);
+                mService.addAppLocked(app.info, null, false, null /* ABI override */,
+                        ZYGOTE_POLICY_FLAG_EMPTY);
             }
         } else {
             mRemovedProcesses.add(app);