Merge "Add client/service process states for broadcast/service/provider" into udc-dev am: 0f529d03a8 am: cb4d966258

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23558767

Change-Id: Ibca4ffa4a1f154459581aa37ba2f69f0c7f067eb
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 6f20563..fc84e13 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -621,7 +621,8 @@
                     try {
                         final ServiceRecord.StartItem si = r.pendingStarts.get(0);
                         startServiceInnerLocked(this, si.intent, r, false, true, si.callingId,
-                                si.mCallingProcessName, r.startRequested, si.mCallingPackageName);
+                                si.mCallingProcessName, si.mCallingProcessState,
+                                r.startRequested, si.mCallingPackageName);
                     } catch (TransactionTooLargeException e) {
                         // Ignore, nobody upstack cares.
                     }
@@ -977,10 +978,22 @@
             fgRequired = false;
         }
 
+        final ProcessRecord callingApp;
+        synchronized (mAm.mPidsSelfLocked) {
+            callingApp = mAm.mPidsSelfLocked.get(callingPid);
+        }
+        final String callingProcessName = callingApp != null
+                ? callingApp.processName : callingPackage;
+        final int callingProcessState =
+                callingApp != null && callingApp.getThread() != null && !callingApp.isKilled()
+                ? callingApp.mState.getCurProcState() : ActivityManager.PROCESS_STATE_UNKNOWN;
+        r.updateProcessStateOnRequest();
+
         // The package could be frozen (meaning it's doing surgery), defer the actual
         // start until the package is unfrozen.
         if (deferServiceBringupIfFrozenLocked(r, service, callingPackage, callingFeatureId,
-                callingUid, callingPid, fgRequired, callerFg, userId,
+                callingUid, callingPid, callingProcessName,
+                callingProcessState, fgRequired, callerFg, userId,
                 backgroundStartPrivileges, false, null)) {
             return null;
         }
@@ -1001,7 +1014,7 @@
         // what realResult contains.
         final ComponentName realResult =
                 startServiceInnerLocked(r, service, callingUid, callingPid,
-                        getCallingProcessNameLocked(callingUid, callingPid, callingPackage),
+                        callingProcessName, callingProcessState,
                         fgRequired, callerFg,
                         backgroundStartPrivileges, callingPackage);
         if (res.aliasComponent != null
@@ -1013,17 +1026,9 @@
         }
     }
 
-    private String getCallingProcessNameLocked(int callingUid, int callingPid,
-            String callingPackage) {
-        synchronized (mAm.mPidsSelfLocked) {
-            final ProcessRecord callingApp = mAm.mPidsSelfLocked.get(callingPid);
-            return callingApp != null ? callingApp.processName : callingPackage;
-        }
-    }
-
     private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service,
-            int callingUid, int callingPid, String callingProcessName, boolean fgRequired,
-            boolean callerFg,
+            int callingUid, int callingPid, String callingProcessName,
+            int callingProcessState, boolean fgRequired, boolean callerFg,
             BackgroundStartPrivileges backgroundStartPrivileges, String callingPackage)
             throws TransactionTooLargeException {
         NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent(
@@ -1037,7 +1042,8 @@
         r.delayedStop = false;
         r.fgRequired = fgRequired;
         r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
-                service, neededGrants, callingUid, callingProcessName, callingPackage));
+                service, neededGrants, callingUid, callingProcessName, callingPackage,
+                callingProcessState));
 
         // We want to allow scheduling user-initiated jobs when the app is running a
         // foreground service that was started in the same conditions that allows for scheduling
@@ -1140,7 +1146,8 @@
             r.allowBgActivityStartsOnServiceStart(backgroundStartPrivileges);
         }
         ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
-                callingUid, callingProcessName, wasStartRequested, callingPackage);
+                callingUid, callingProcessName, callingProcessState,
+                wasStartRequested, callingPackage);
         return cmp;
     }
 
@@ -1244,7 +1251,8 @@
     @GuardedBy("mAm")
     private boolean deferServiceBringupIfFrozenLocked(ServiceRecord s, Intent serviceIntent,
             String callingPackage, @Nullable String callingFeatureId,
-            int callingUid, int callingPid, boolean fgRequired, boolean callerFg, int userId,
+            int callingUid, int callingPid, String callingProcessName,
+            int callingProcessState, boolean fgRequired, boolean callerFg, int userId,
             BackgroundStartPrivileges backgroundStartPrivileges,
             boolean isBinding, IServiceConnection connection) {
         final PackageManagerInternal pm = mAm.getPackageManagerInternal();
@@ -1258,8 +1266,6 @@
             curPendingBringups = new ArrayList<>();
             mPendingBringups.put(s, curPendingBringups);
         }
-        final String callingProcessName = getCallingProcessNameLocked(
-                callingUid, callingPid, callingPackage);
         curPendingBringups.add(new Runnable() {
             @Override
             public void run() {
@@ -1291,7 +1297,7 @@
                     } else { // Starting a service
                         try {
                             startServiceInnerLocked(s, serviceIntent, callingUid, callingPid,
-                                    callingProcessName, fgRequired, callerFg,
+                                    callingProcessName, callingProcessState, fgRequired, callerFg,
                                     backgroundStartPrivileges, callingPackage);
                         } catch (TransactionTooLargeException e) {
                             /* ignore - local call */
@@ -1338,7 +1344,8 @@
 
     ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
             boolean callerFg, boolean addToStarting, int callingUid, String callingProcessName,
-            boolean wasStartRequested, String callingPackage) throws TransactionTooLargeException {
+            int callingProcessState, boolean wasStartRequested, String callingPackage)
+            throws TransactionTooLargeException {
         synchronized (mAm.mProcessStats.mLock) {
             final ServiceState stracker = r.getTracker();
             if (stracker != null) {
@@ -1381,7 +1388,9 @@
                 getShortServiceNameForStats(r),
                 packageState,
                 packageName,
-                callingPackage);
+                callingPackage,
+                callingProcessState,
+                r.mProcessStateOnRequest);
 
         if (r.startRequested && addToStarting) {
             boolean first = smap.mStartingBackground.size() == 0;
@@ -3611,11 +3620,22 @@
             return 0;
         }
 
+        final ProcessRecord callingApp;
+        synchronized (mAm.mPidsSelfLocked) {
+            callingApp = mAm.mPidsSelfLocked.get(callingPid);
+        }
+        final String callingProcessName = callingApp != null
+                ? callingApp.processName : callingPackage;
+        final int callingProcessState =
+                callingApp != null && callingApp.getThread() != null && !callingApp.isKilled()
+                ? callingApp.mState.getCurProcState() : ActivityManager.PROCESS_STATE_UNKNOWN;
+        s.updateProcessStateOnRequest();
+
         // The package could be frozen (meaning it's doing surgery), defer the actual
         // binding until the package is unfrozen.
         boolean packageFrozen = deferServiceBringupIfFrozenLocked(s, service, callingPackage, null,
-                callingUid, callingPid, false, callerFg, userId, BackgroundStartPrivileges.NONE,
-                true, connection);
+                callingUid, callingPid, callingProcessName, callingProcessState,
+                false, callerFg, userId, BackgroundStartPrivileges.NONE, true, connection);
 
         // If permissions need a review before any of the app components can run,
         // we schedule binding to the service but do not start its process, then
@@ -3756,7 +3776,9 @@
                     getShortServiceNameForStats(s),
                     packageState,
                     s.packageName,
-                    callerApp.info.packageName);
+                    callerApp.info.packageName,
+                    callerApp.mState.getCurProcState(),
+                    s.mProcessStateOnRequest);
 
             if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
                     + ": received=" + b.intent.received
@@ -5355,7 +5377,7 @@
         // be called.
         if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
             r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
-                    null, null, 0, null, null));
+                    null, null, 0, null, null, ActivityManager.PROCESS_STATE_UNKNOWN));
         }
 
         sendServiceArgsLocked(r, execInFg, true);
@@ -6351,7 +6373,8 @@
                     stopServiceLocked(sr, true);
                 } else {
                     sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
-                            sr.getLastStartId(), baseIntent, null, 0, null, null));
+                            sr.getLastStartId(), baseIntent, null, 0, null, null,
+                            ActivityManager.PROCESS_STATE_UNKNOWN));
                     if (sr.app != null && sr.app.getThread() != null) {
                         // We always run in the foreground, since this is called as
                         // part of the "remove task" UI operation.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6d55058..a94fdad 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1176,20 +1176,24 @@
         public Intent intent;
         public boolean deferUntilActive;
         public int originalCallingUid;
+        /** The snapshot process state of the app who sent this broadcast */
+        public int originalCallingAppProcessState;
 
         public static StickyBroadcast create(Intent intent, boolean deferUntilActive,
-                int originalCallingUid) {
+                int originalCallingUid, int originalCallingAppProcessState) {
             final StickyBroadcast b = new StickyBroadcast();
             b.intent = intent;
             b.deferUntilActive = deferUntilActive;
             b.originalCallingUid = originalCallingUid;
+            b.originalCallingAppProcessState = originalCallingAppProcessState;
             return b;
         }
 
         @Override
         public String toString() {
             return "{intent=" + intent + ", defer=" + deferUntilActive + ", originalCallingUid="
-                    + originalCallingUid + "}";
+                    + originalCallingUid + ", originalCallingAppProcessState="
+                    + originalCallingAppProcessState + "}";
         }
     }
 
@@ -14042,7 +14046,8 @@
                             receivers, null, null, 0, null, null, false, true, true, -1,
                             originalStickyCallingUid, BackgroundStartPrivileges.NONE,
                             false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */,
-                            null /* filterExtrasForReceiver */);
+                            null /* filterExtrasForReceiver */,
+                            broadcast.originalCallingAppProcessState);
                     queue.enqueueBroadcastLocked(r);
                 }
             }
@@ -14857,6 +14862,7 @@
             }
         }
 
+        final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid);
         // Add to the sticky list if requested.
         if (sticky) {
             if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
@@ -14919,12 +14925,13 @@
                 if (intent.filterEquals(list.get(i).intent)) {
                     // This sticky already exists, replace it.
                     list.set(i, StickyBroadcast.create(new Intent(intent), deferUntilActive,
-                            callingUid));
+                            callingUid, callerAppProcessState));
                     break;
                 }
             }
             if (i >= stickiesCount) {
-                list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive, callingUid));
+                list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive, callingUid,
+                        callerAppProcessState));
             }
         }
 
@@ -15007,7 +15014,8 @@
                     requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
                     registeredReceivers, resultToApp, resultTo, resultCode, resultData,
                     resultExtras, ordered, sticky, false, userId,
-                    backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver);
+                    backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
+                    callerAppProcessState);
             if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
             queue.enqueueBroadcastLocked(r);
             registeredReceivers = null;
@@ -15101,7 +15109,8 @@
                     requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
                     receivers, resultToApp, resultTo, resultCode, resultData, resultExtras,
                     ordered, sticky, false, userId,
-                    backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver);
+                    backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
+                    callerAppProcessState);
 
             if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
             queue.enqueueBroadcastLocked(r);
@@ -15118,6 +15127,19 @@
         return ActivityManager.BROADCAST_SUCCESS;
     }
 
+    @GuardedBy("this")
+    private int getRealProcessStateLocked(ProcessRecord app, int pid) {
+        if (app == null) {
+            synchronized (mPidsSelfLocked) {
+                app = mPidsSelfLocked.get(pid);
+            }
+        }
+        if (app != null && app.getThread() != null && !app.isKilled()) {
+            return app.mState.getCurProcState();
+        }
+        return PROCESS_STATE_NONEXISTENT;
+    }
+
     @VisibleForTesting
     ArrayList<StickyBroadcast> getStickyBroadcasts(String action, int userId) {
         final ArrayMap<String, ArrayList<StickyBroadcast>> stickyBroadcasts =
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 4b6d324..a80ad59 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -106,6 +106,12 @@
     long lastCpuDelayTime;
 
     /**
+     * Snapshotted value of {@link ProcessStateRecord#getCurProcState()} before
+     * dispatching the current broadcast to the receiver in this process.
+     */
+    int lastProcessState;
+
+    /**
      * Ordered collection of broadcasts that are waiting to be dispatched to
      * this process, as a pair of {@link BroadcastRecord} and the index into
      * {@link BroadcastRecord#receivers} that represents the receiver.
diff --git a/services/core/java/com/android/server/am/BroadcastQueueImpl.java b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
index 8688f25..f13dc89 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
@@ -269,7 +269,10 @@
                                 Activity.RESULT_CANCELED, null, null,
                                 false, false, oldRecord.shareIdentity, oldRecord.userId,
                                 oldRecord.callingUid, r.callingUid, r.callerPackage,
-                                SystemClock.uptimeMillis() - oldRecord.enqueueTime, 0, 0);
+                                SystemClock.uptimeMillis() - oldRecord.enqueueTime, 0, 0,
+                                oldRecord.resultToApp != null
+                                        ? oldRecord.resultToApp.mState.getCurProcState()
+                                        : ActivityManager.PROCESS_STATE_UNKNOWN);
                     } catch (RemoteException e) {
                         Slog.w(TAG, "Failure ["
                                 + mQueueName + "] sending broadcast result of "
@@ -367,6 +370,7 @@
         }
 
         r.curApp = app;
+        r.curAppLastProcessState = app.mState.getCurProcState();
         final ProcessReceiverRecord prr = app.mReceivers;
         prr.addCurReceiver(r);
         app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
@@ -418,6 +422,7 @@
                 if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                         "Process cur broadcast " + r + ": NOT STARTED!");
                 r.curApp = null;
+                r.curAppLastProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
                 prr.removeCurReceiver(r);
             }
         }
@@ -620,7 +625,8 @@
                     r.getDeliveryGroupPolicy(),
                     r.intent.getFlags(),
                     BroadcastRecord.getReceiverPriority(curReceiver),
-                    r.callerProcState);
+                    r.callerProcState,
+                    r.curAppLastProcessState);
         }
         if (state == BroadcastRecord.IDLE) {
             Slog.w(TAG_BROADCAST, "finishReceiver [" + mQueueName + "] called but state is IDLE");
@@ -682,6 +688,7 @@
         r.curFilter = null;
         r.curReceiver = null;
         r.curApp = null;
+        r.curAppLastProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
         r.curFilteredExtras = null;
         r.mWasReceiverAppStopped = false;
         mPendingBroadcast = null;
@@ -751,7 +758,8 @@
             Intent intent, int resultCode, String data, Bundle extras,
             boolean ordered, boolean sticky, boolean shareIdentity, int sendingUser,
             int receiverUid, int callingUid, String callingPackage,
-            long dispatchDelay, long receiveDelay, int priority) throws RemoteException {
+            long dispatchDelay, long receiveDelay, int priority,
+            int receiverProcessState) throws RemoteException {
         // If the broadcaster opted-in to sharing their identity, then expose package visibility for
         // the receiver.
         if (shareIdentity) {
@@ -802,7 +810,7 @@
                     SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
                     app != null ? app.info.packageName : null, callingPackage,
                     r.calculateTypeForLogging(), r.getDeliveryGroupPolicy(), r.intent.getFlags(),
-                    priority, r.callerProcState);
+                    priority, r.callerProcState, receiverProcessState);
         }
     }
 
@@ -849,6 +857,7 @@
                 // things that directly call the IActivityManager API, which
                 // are already core system stuff so don't matter for this.
                 r.curApp = filter.receiverList.app;
+                r.curAppLastProcessState = r.curApp.mState.getCurProcState();
                 filter.receiverList.app.mReceivers.addCurReceiver(r);
                 mService.enqueueOomAdjTargetLocked(r.curApp);
                 mService.updateOomAdjPendingTargetsLocked(
@@ -883,7 +892,10 @@
                         r.resultExtras, r.ordered, r.initialSticky, r.shareIdentity, r.userId,
                         filter.receiverList.uid, r.callingUid, r.callerPackage,
                         r.dispatchTime - r.enqueueTime,
-                        r.receiverTime - r.dispatchTime, filter.getPriority());
+                        r.receiverTime - r.dispatchTime, filter.getPriority(),
+                        filter.receiverList.app != null
+                                ? filter.receiverList.app.mState.getCurProcState()
+                                : ActivityManager.PROCESS_STATE_UNKNOWN);
                 // parallel broadcasts are fire-and-forget, not bookended by a call to
                 // finishReceiverLocked(), so we manage their activity-start token here
                 if (filter.receiverList.app != null
@@ -1174,7 +1186,10 @@
                                     r.resultData, r.resultExtras, false, false, r.shareIdentity,
                                     r.userId, r.callingUid, r.callingUid, r.callerPackage,
                                     r.dispatchTime - r.enqueueTime,
-                                    now - r.dispatchTime, 0);
+                                    now - r.dispatchTime, 0,
+                                    r.resultToApp != null
+                                            ? r.resultToApp.mState.getCurProcState()
+                                            : ActivityManager.PROCESS_STATE_UNKNOWN);
                             logBootCompletedBroadcastCompletionLatencyIfPossible(r);
                             // Set this to null so that the reference
                             // (local and remote) isn't kept in the mBroadcastHistory.
@@ -1480,6 +1495,7 @@
                         r.intent.getAction(), r.getHostingRecordTriggerType()),
                 isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
                 (r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false);
+        r.curAppLastProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
         if (r.curApp == null) {
             // Ah, this recipient is unavailable.  Finish it if necessary,
             // and mark the broadcast record as ready for the next.
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 8380308..397eef4 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1002,6 +1002,7 @@
                     mService.mPackageManagerInt.grantImplicitAccess(r.userId, r.intent,
                             UserHandle.getAppId(app.uid), r.callingUid, true);
                 }
+                queue.lastProcessState = app.mState.getCurProcState();
                 if (receiver instanceof BroadcastFilter) {
                     notifyScheduleRegisteredReceiver(app, r, (BroadcastFilter) receiver);
                     thread.scheduleRegisteredReceiver(
@@ -1914,12 +1915,16 @@
                 ? BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__RUNTIME
                 : BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST;
         final int type;
+        final int receiverProcessState;
         if (queue == null) {
             type = BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_UNKNOWN;
+            receiverProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
         } else if (queue.getActiveViaColdStart()) {
             type = BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
+            receiverProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
         } else {
             type = BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM;
+            receiverProcessState = queue.lastProcessState;
         }
         // With the new per-process queues, there's no delay between being
         // "dispatched" and "scheduled", so we report no "receive delay"
@@ -1934,7 +1939,8 @@
                     receiverType, type, dispatchDelay, receiveDelay, finishDelay, packageState,
                     app != null ? app.info.packageName : null, r.callerPackage,
                     r.calculateTypeForLogging(), r.getDeliveryGroupPolicy(), r.intent.getFlags(),
-                    BroadcastRecord.getReceiverPriority(receiver), r.callerProcState);
+                    BroadcastRecord.getReceiverPriority(receiver), r.callerProcState,
+                    receiverProcessState);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 67d43fd..198adcb 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -44,7 +44,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UptimeMillisLong;
-import android.app.ActivityManager;
 import android.app.ActivityManager.ProcessState;
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
@@ -271,6 +270,8 @@
     BroadcastFilter curFilter;  // the registered receiver currently running.
     Bundle curFilteredExtras;   // the bundle that has been filtered by the package visibility rules
 
+    int curAppLastProcessState; // The last process state of the current receiver before receiving
+
     boolean mIsReceiverAppRunning; // Was the receiver's app already running.
 
     boolean mWasReceiverAppStopped; // Was the receiver app stopped prior to starting
@@ -432,13 +433,14 @@
             boolean initialSticky, int userId,
             @NonNull BackgroundStartPrivileges backgroundStartPrivileges,
             boolean timeoutExempt,
-            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
+            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
+            int callerAppProcessState) {
         this(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid,
                 callingUid, callerInstantApp, resolvedType, requiredPermissions,
                 excludedPermissions, excludedPackages, appOp, options, receivers, resultToApp,
                 resultTo, resultCode, resultData, resultExtras, serialized, sticky,
                 initialSticky, userId, -1, backgroundStartPrivileges, timeoutExempt,
-                filterExtrasForReceiver);
+                filterExtrasForReceiver, callerAppProcessState);
     }
 
     BroadcastRecord(BroadcastQueue _queue,
@@ -453,7 +455,8 @@
             boolean _initialSticky, int _userId, int originalStickyCallingUid,
             @NonNull BackgroundStartPrivileges backgroundStartPrivileges,
             boolean timeoutExempt,
-            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
+            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
+            int callerAppProcessState) {
         if (_intent == null) {
             throw new NullPointerException("Can't construct with a null intent");
         }
@@ -465,8 +468,7 @@
         callerFeatureId = _callerFeatureId;
         callingPid = _callingPid;
         callingUid = _callingUid;
-        callerProcState = callerApp == null ? ActivityManager.PROCESS_STATE_UNKNOWN
-                : callerApp.getCurProcState();
+        callerProcState = callerAppProcessState;
         callerInstantApp = _callerInstantApp;
         callerInstrumented = isCallerInstrumented(_callerApp, _callingUid);
         resolvedType = _resolvedType;
@@ -606,7 +608,8 @@
                 requiredPermissions, excludedPermissions, excludedPackages, appOp, options,
                 splitReceivers, resultToApp, resultTo, resultCode, resultData, resultExtras,
                 ordered, sticky, initialSticky, userId,
-                mBackgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver);
+                mBackgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
+                callerProcState);
         split.enqueueTime = this.enqueueTime;
         split.enqueueRealTime = this.enqueueRealTime;
         split.enqueueClockTime = this.enqueueClockTime;
@@ -686,7 +689,7 @@
                     uid2receiverList.valueAt(i), null /* _resultToApp */, null /* _resultTo */,
                     resultCode, resultData, resultExtras, ordered, sticky, initialSticky, userId,
                     mBackgroundStartPrivileges, timeoutExempt,
-                    filterExtrasForReceiver);
+                    filterExtrasForReceiver, callerProcState);
             br.enqueueTime = this.enqueueTime;
             br.enqueueRealTime = this.enqueueRealTime;
             br.enqueueClockTime = this.enqueueClockTime;
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index e744eee..3f7d8ba 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -246,9 +246,13 @@
                 }
             }
 
+            final int callingProcessState = r != null
+                    ? r.mState.getCurProcState() : ActivityManager.PROCESS_STATE_UNKNOWN;
+
             if (providerRunning) {
                 cpi = cpr.info;
 
+
                 if (r != null && cpr.canRunHere(r)) {
                     checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
                             cpr.name.flattenToShortString(), startTime);
@@ -266,7 +270,8 @@
                             r.uid, callingUid,
                             PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
                             PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
-                            cpi.packageName, callingPackage);
+                            cpi.packageName, callingPackage,
+                            callingProcessState, callingProcessState);
                     return holder;
                 }
 
@@ -282,6 +287,8 @@
                 checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
                         cpr.name.flattenToShortString(), startTime);
 
+                final int providerProcessState = cpr.proc.mState.getCurProcState();
+
                 final long origId = Binder.clearCallingIdentity();
                 try {
                     checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
@@ -338,7 +345,8 @@
                                 cpr.proc.uid, callingUid,
                                 PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
                                 PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
-                                cpi.packageName, callingPackage);
+                                cpi.packageName, callingPackage,
+                                callingProcessState, providerProcessState);
                     }
                 } finally {
                     Binder.restoreCallingIdentity(origId);
@@ -516,7 +524,8 @@
                                     proc.uid, callingUid,
                                     PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
                                     PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
-                                    cpi.packageName, callingPackage);
+                                    cpi.packageName, callingPackage,
+                                    callingProcessState, proc.mState.getCurProcState());
                         } else {
                             final int packageState =
                                     ((cpr.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0)
@@ -541,7 +550,8 @@
                                     PROVIDER_ACQUISITION_EVENT_REPORTED,
                                     proc.uid, callingUid,
                                     PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD,
-                                    packageState, cpi.packageName, callingPackage);
+                                    packageState, cpi.packageName, callingPackage,
+                                    callingProcessState, ActivityManager.PROCESS_STATE_NONEXISTENT);
                         }
                         cpr.launchingApp = proc;
                         mLaunchingProviders.add(cpr);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index dccbb0a..0f5defb 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
 import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_BOUND_SERVICE;
@@ -244,6 +245,11 @@
      */
     long mRestartSchedulingTime;
 
+    /**
+     * The snapshot process state when the service is requested (either start or bind).
+     */
+    int mProcessStateOnRequest;
+
     static class StartItem {
         final ServiceRecord sr;
         final boolean taskRemoved;
@@ -253,6 +259,7 @@
         final Intent intent;
         final NeededUriGrants neededGrants;
         final @Nullable String mCallingPackageName;
+        final int mCallingProcessState;
         long deliveredTime;
         int deliveryCount;
         int doneExecutingCount;
@@ -262,7 +269,8 @@
 
         StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id,
                 Intent _intent, NeededUriGrants _neededGrants, int _callingId,
-                String callingProcessName, @Nullable String callingPackageName) {
+                String callingProcessName, @Nullable String callingPackageName,
+                int callingProcessState) {
             sr = _sr;
             taskRemoved = _taskRemoved;
             id = _id;
@@ -271,6 +279,7 @@
             callingId = _callingId;
             mCallingProcessName = callingProcessName;
             mCallingPackageName = callingPackageName;
+            mCallingProcessState = callingProcessState;
         }
 
         UriPermissionOwner getUriPermissionsLocked() {
@@ -873,6 +882,7 @@
             app.mServices.updateHostingComonentTypeForBindingsLocked();
         }
         app = proc;
+        updateProcessStateOnRequest();
         if (pendingConnectionGroup > 0 && proc != null) {
             final ProcessServiceRecord psr = proc.mServices;
             psr.setConnectionService(this);
@@ -899,6 +909,11 @@
         }
     }
 
+    void updateProcessStateOnRequest() {
+        mProcessStateOnRequest = app != null && app.getThread() != null && !app.isKilled()
+                ? app.mState.getCurProcState() : PROCESS_STATE_NONEXISTENT;
+    }
+
     @NonNull
     ArrayMap<IBinder, ArrayList<ConnectionRecord>> getConnections() {
         return connections;
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index a614c4d..2bc66ac 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -27,6 +27,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
 import static android.util.DebugUtils.valueToString;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -742,24 +743,24 @@
 
         broadcastIntent(intent1, null, true);
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
-                StickyBroadcast.create(intent1, false, Process.myUid()));
+                StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertNull(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER));
         assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER));
 
         broadcastIntent(intent2, options.toBundle(), true);
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
-                StickyBroadcast.create(intent1, false, Process.myUid()));
+                StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER),
-                StickyBroadcast.create(intent2, true, Process.myUid()));
+                StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER));
 
         broadcastIntent(intent3, null, true);
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
-                StickyBroadcast.create(intent1, false, Process.myUid()));
+                StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER),
-                StickyBroadcast.create(intent2, true, Process.myUid()));
+                StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER),
-                StickyBroadcast.create(intent3, false, Process.myUid()));
+                StickyBroadcast.create(intent3, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
     }
 
     @SuppressWarnings("GuardedBy")
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 582685c..ccaaa87 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
+
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED;
 import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
@@ -246,7 +248,7 @@
         return new BroadcastRecord(mImpl, intent, mProcess, PACKAGE_RED, null, 21, 42, false, null,
                 null, null, null, AppOpsManager.OP_NONE, options, receivers, null, resultTo,
                 Activity.RESULT_OK, null, null, ordered, false, false, UserHandle.USER_SYSTEM,
-                BackgroundStartPrivileges.NONE, false, null);
+                BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
     }
 
     private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
@@ -1407,7 +1409,7 @@
                 eq(BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST),
                 eq(BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD),
                 anyLong(), anyLong(), anyLong(), anyInt(), nullable(String.class),
-                anyString(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()),
+                anyString(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()),
                 times(1));
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index 03231ec..0f75ea5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FINISH_RECEIVER;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_RECEIVER;
 import static android.os.UserHandle.USER_SYSTEM;
@@ -611,7 +612,7 @@
                 callerApp.getPid(), callerApp.info.uid, false, null, null, null, null,
                 AppOpsManager.OP_NONE, options, receivers, callerApp, resultTo,
                 Activity.RESULT_OK, null, resultExtras, ordered, false, false, userId,
-                BackgroundStartPrivileges.NONE, false, null);
+                BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
     }
 
     private void assertHealth() {
@@ -1599,7 +1600,7 @@
                 null, null, null, null, AppOpsManager.OP_NONE, BroadcastOptions.makeBasic(),
                 List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), null, null,
                 Activity.RESULT_OK, null, null, false, false, false, UserHandle.USER_SYSTEM,
-                backgroundStartPrivileges, false, null);
+                backgroundStartPrivileges, false, null, PROCESS_STATE_UNKNOWN);
         enqueueBroadcast(r);
 
         waitForIdle();
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
index 08952ea..f0efb79 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
 import static android.app.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
 import static android.content.Intent.ACTION_BOOT_COMPLETED;
 import static android.content.Intent.ACTION_LOCKED_BOOT_COMPLETED;
@@ -958,7 +959,8 @@
                 userId,
                 BackgroundStartPrivileges.NONE,
                 false /* timeoutExempt */,
-                filterExtrasForReceiver);
+                filterExtrasForReceiver,
+                PROCESS_STATE_UNKNOWN);
     }
 
     private static int getAppId(int i) {