summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java30
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java19
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java42
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java14
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java2
7 files changed, 82 insertions, 30 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2f1f91e1734a..026430b5469d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -333,7 +333,8 @@ public final class ActiveServices {
}
r.delayed = false;
try {
- startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true);
+ startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true,
+ false);
} catch (TransactionTooLargeException e) {
// Ignore, nobody upstack cares.
}
@@ -643,7 +644,8 @@ public final class ActiveServices {
SERVICE_BG_ACTIVITY_START_TIMEOUT_MS);
}
}
- ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
+ ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
+ allowBackgroundActivityStarts);
return cmp;
}
@@ -702,7 +704,8 @@ public final class ActiveServices {
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
- boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
+ boolean callerFg, boolean addToStarting, boolean allowBackgroundActivityStarts)
+ throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
@@ -713,7 +716,8 @@ public final class ActiveServices {
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
- String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
+ String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false,
+ allowBackgroundActivityStarts);
if (error != null) {
return new ComponentName("!!", error);
}
@@ -1645,7 +1649,7 @@ public final class ActiveServices {
try {
bringUpServiceLocked(serviceRecord,
serviceIntent.getFlags(),
- callerFg, false, false);
+ callerFg, false, false, false);
} catch (RemoteException e) {
/* ignore - local call */
}
@@ -1748,7 +1752,7 @@ public final class ActiveServices {
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
- permissionsReviewRequired) != null) {
+ permissionsReviewRequired, false) != null) {
return 0;
}
}
@@ -2418,7 +2422,8 @@ public final class ActiveServices {
return;
}
try {
- bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false);
+ bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false,
+ false);
} catch (TransactionTooLargeException e) {
// Ignore, it's been logged and nothing upstack cares.
}
@@ -2463,8 +2468,8 @@ public final class ActiveServices {
}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
- boolean whileRestarting, boolean permissionsReviewRequired)
- throws TransactionTooLargeException {
+ boolean whileRestarting, boolean permissionsReviewRequired,
+ boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
//Slog.i(TAG, "Bring up service:");
//r.dump(" ");
@@ -2575,6 +2580,13 @@ public final class ActiveServices {
}
}
+ if (app != null && allowBackgroundActivityStarts) {
+ app.addAllowBackgroundActivityStartsToken(r);
+ // schedule removal of the whitelisting token after the timeout
+ removeAllowBackgroundActivityStartsServiceToken(app, r,
+ SERVICE_BG_ACTIVITY_START_TIMEOUT_MS);
+ }
+
if (r.fgRequired) {
if (DEBUG_FOREGROUND_SERVICE) {
Slog.v(TAG, "Whitelisting " + UserHandle.formatUid(r.appInfo.uid)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 94fc552fa1c2..380cc25e15d9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14997,7 +14997,7 @@ public class ActivityManagerService extends IActivityManager.Stub
oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
oldRecord.intent,
Activity.RESULT_CANCELED, null, null,
- false, false, oldRecord.userId);
+ false, false, oldRecord.userId, oldRecord);
} catch (RemoteException e) {
Slog.w(TAG, "Failure ["
+ queue.mQueueName + "] sending broadcast result of "
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index a11ebfd3e419..f0b137a6ccb1 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -74,6 +74,9 @@ public final class BroadcastQueue {
static final int MAX_BROADCAST_SUMMARY_HISTORY
= ActivityManager.isLowRamDeviceStatic() ? 25 : 300;
+ // For how long after a whitelisted receiver's start its process can start a background activity
+ private static final int RECEIVER_BG_ACTIVITY_START_TIMEOUT_MS = 10_000;
+
final ActivityManagerService mService;
/**
@@ -551,13 +554,23 @@ public final class BroadcastQueue {
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
+ boolean ordered, boolean sticky, int sendingUser, BroadcastRecord br)
+ throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null) {
if (app.thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
try {
+ if (br.allowBackgroundActivityStarts) {
+ app.addAllowBackgroundActivityStartsToken(br);
+ // schedule removal of the whitelisting token after the timeout
+ mHandler.postDelayed(() -> {
+ if (app != null) {
+ app.removeAllowBackgroundActivityStartsToken(br);
+ }
+ }, RECEIVER_BG_ACTIVITY_START_TIMEOUT_MS);
+ }
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
// TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
@@ -783,7 +796,7 @@ public final class BroadcastQueue {
} else {
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
- r.resultExtras, r.ordered, r.initialSticky, r.userId);
+ r.resultExtras, r.ordered, r.initialSticky, r.userId, r);
}
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
@@ -1082,7 +1095,7 @@ public final class BroadcastQueue {
}
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, false, false, r.userId);
+ r.resultData, r.resultExtras, false, false, r.userId, r);
// Set this to null so that the reference
// (local and remote) isn't kept in the mBroadcastHistory.
r.resultTo = null;
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 0b27a8ad77dc..af56352b8cc0 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -384,6 +384,9 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
final boolean allowTrampoline = uid != callingUid
&& controller.mAtmInternal.isUidForeground(callingUid);
+ // note: we on purpose don't pass in the information about the PendingIntent's creator,
+ // like pid or ProcessRecord, to the ActivityTaskManagerInternal calls below, because
+ // it's not unusual for the creator's process to not be alive at this time
switch (key.type) {
case ActivityManager.INTENT_SENDER_ACTIVITY:
try {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 1d71d8764bf7..678a896bddbc 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -753,8 +753,8 @@ class ActivityStarter {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"shouldAbortBackgroundActivityStart");
abortBackgroundStart = shouldAbortBackgroundActivityStart(callingUid, callingPid,
- callingPackage, realCallingUid, callerApp, originatingPendingIntent,
- allowBackgroundActivityStart, intent);
+ callingPackage, realCallingUid, realCallingPid, callerApp,
+ originatingPendingIntent, allowBackgroundActivityStart, intent);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -914,22 +914,14 @@ class ActivityStarter {
}
private boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
- final String callingPackage, int realCallingUid, WindowProcessController callerApp,
- PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart,
- Intent intent) {
+ final String callingPackage, int realCallingUid, int realCallingPid,
+ WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
+ boolean allowBackgroundActivityStart, Intent intent) {
// don't abort for the most important UIDs
if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID
|| callingUid == Process.NFC_UID) {
return false;
}
- // don't abort if the callerApp has any visible activity
- if (callerApp != null && callerApp.hasForegroundActivities()) {
- return false;
- }
- // don't abort if the callerApp is instrumenting with background activity starts privileges
- if (callerApp != null && callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) {
- return false;
- }
// don't abort if the callingUid is in the foreground or is a persistent system process
final int callingUidProcState = mService.getUidStateLocked(callingUid);
final boolean callingUidHasAnyVisibleWindow =
@@ -967,9 +959,26 @@ class ActivityStarter {
return false;
}
}
- // don't abort if the caller is currently temporarily whitelisted
- if (callerApp != null && callerApp.areBackgroundActivityStartsAllowed()) {
- return false;
+ // If we don't have callerApp at this point, no caller was provided to startActivity().
+ // That's the case for PendingIntent-based starts, since the creator's process might not be
+ // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
+ // caller, so that we can make the decision based on its foreground/whitelisted state.
+ if (callerApp == null) {
+ callerApp = mService.getProcessController(realCallingPid, realCallingUid);
+ }
+ if (callerApp != null) {
+ // don't abort if the callerApp has any visible activity
+ if (callerApp.hasForegroundActivities()) {
+ return false;
+ }
+ // don't abort if the callerApp is instrumenting with background activity starts privs
+ if (callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) {
+ return false;
+ }
+ // don't abort if the caller is currently temporarily whitelisted
+ if (callerApp.areBackgroundActivityStartsAllowed()) {
+ return false;
+ }
}
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
@@ -996,6 +1005,7 @@ class ActivityStarter {
+ "; originatingPendingIntent: " + originatingPendingIntent
+ "; isBgStartWhitelisted: " + allowBackgroundActivityStart
+ "; intent: " + intent
+ + "; callerApp: " + callerApp
+ "]");
// log aborted activity start to TRON
if (mService.isActivityStartsLoggingEnabled()) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b6bac6131986..7aa34819692b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5666,6 +5666,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return null;
}
+ WindowProcessController getProcessController(int pid, int uid) {
+ final ArrayMap<String, SparseArray<WindowProcessController>> pmap = mProcessNames.getMap();
+ for (int i = pmap.size()-1; i >= 0; i--) {
+ final SparseArray<WindowProcessController> procs = pmap.valueAt(i);
+ for (int j = procs.size() - 1; j >= 0; j--) {
+ final WindowProcessController proc = procs.valueAt(j);
+ if (UserHandle.isApp(uid) && proc.getPid() == pid && proc.mUid == uid) {
+ return proc;
+ }
+ }
+ }
+ return null;
+ }
+
int getUidStateLocked(int uid) {
return mActiveUids.get(uid, PROCESS_STATE_NONEXISTENT);
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 0fb900a6eaf4..465f4131ee8e 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -986,7 +986,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
@Override
public String toString() {
- return mOwner.toString();
+ return mOwner != null ? mOwner.toString() : null;
}
public void dump(PrintWriter pw, String prefix) {