summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Michal Karpinski <mkarpinski@google.com> 2019-01-10 16:45:59 +0000
committer Michal Karpinski <mkarpinski@google.com> 2019-01-10 16:46:22 +0000
commitc8aa91bd0a0af06146f1ba60aa049c77316fff59 (patch)
treeea8f1e7295c7f88ac469746e5f7f5a1fb216ca92
parent58514eaa6f1d3f43d83d0080b21522dece5f2739 (diff)
Temporarily whitelist processes to open activities from background
when service-based PendingIntent was whitelisted Extends the mechanism added for broadcasts in ag/5779089. The process can start activity from background when whitelisted PendingIntent-based Service was started - for the next 10 seconds, or until the service is stopped, whichever happens sooner. For now, all this is only wired for notifications. Bug: 110956953 Test: atest WmTests:ActivityStarterTests Test: manual with Calendar notifications that are known for doing Service trampolines Change-Id: If6ed2f5e22403c4df5abb6cf876ae89505e57380
-rw-r--r--core/java/android/app/ActivityManagerInternal.java4
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java32
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java7
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java8
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java2
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java4
6 files changed, 50 insertions, 7 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 9d44e58112c5..c90e40411240 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -258,8 +258,8 @@ public abstract class ActivityManagerInternal {
Bundle resultExtras, String requiredPermission, Bundle bOptions, boolean serialized,
boolean sticky, int userId, boolean allowBackgroundActivityStarts);
public abstract ComponentName startServiceInPackage(int uid, Intent service,
- String resolvedType, boolean fgRequired, String callingPackage, int userId)
- throws TransactionTooLargeException;
+ String resolvedType, boolean fgRequired, String callingPackage, int userId,
+ boolean allowBackgroundActivityStarts) throws TransactionTooLargeException;
public abstract void disconnectActivityFromServices(Object connectionHolder);
public abstract void cleanUpServices(int userId, ComponentName component, Intent baseIntent);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index ed39d8302bf7..83812adf173c 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -130,6 +130,9 @@ public final class ActiveServices {
// calling startForeground() before we ANR + stop it.
static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000;
+ // For how long after a whitelisted service's start its process can start a background activity
+ private static final int SERVICE_BG_ACTIVITY_START_TIMEOUT_MS = 10*1000;
+
final ActivityManagerService mAm;
// Maximum number of services that we allow to start in the background
@@ -398,6 +401,14 @@ public final class ActiveServices {
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
+ return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
+ callingPackage, userId, false);
+ }
+
+ ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
+ int callingPid, int callingUid, boolean fgRequired, String callingPackage,
+ final int userId, boolean allowBackgroundActivityStarts)
+ throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
@@ -622,10 +633,28 @@ public final class ActiveServices {
}
}
+ if (allowBackgroundActivityStarts) {
+ ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
+ if (proc != null) {
+ proc.addAllowBackgroundActivityStartsToken(r);
+ // schedule removal of the whitelisting token after the timeout
+ removeAllowBackgroundActivityStartsServiceToken(proc, r,
+ SERVICE_BG_ACTIVITY_START_TIMEOUT_MS);
+ }
+ }
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
+ private void removeAllowBackgroundActivityStartsServiceToken(ProcessRecord proc,
+ ServiceRecord r, int delayMillis) {
+ mAm.mHandler.postDelayed(() -> {
+ if (proc != null) {
+ proc.removeAllowBackgroundActivityStartsToken(r);
+ }
+ }, delayMillis);
+ }
+
private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r,
String callingPackage, int callingUid, Intent service, boolean callerFg,
final int userId) {
@@ -752,6 +781,9 @@ public final class ActiveServices {
if (r.record != null) {
final long origId = Binder.clearCallingIdentity();
try {
+ // immediately remove bg activity whitelisting token if there was one
+ removeAllowBackgroundActivityStartsServiceToken(callerApp, r.record,
+ 0 /* delayMillis */);
stopServiceLocked(r.record);
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4f21ee8d8624..6b9d144e0498 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19478,8 +19478,8 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
- boolean fgRequired, String callingPackage, int userId)
- throws TransactionTooLargeException {
+ boolean fgRequired, String callingPackage, int userId,
+ boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
synchronized(ActivityManagerService.this) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"startServiceInPackage: " + service + " type=" + resolvedType);
@@ -19487,7 +19487,8 @@ public class ActivityManagerService extends IActivityManager.Stub
ComponentName res;
try {
res = mServices.startServiceLocked(null, service,
- resolvedType, -1, uid, fgRequired, callingPackage, userId);
+ resolvedType, -1, uid, fgRequired, callingPackage, userId,
+ allowBackgroundActivityStarts);
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index b675d9d4f9cf..98c9ad66bc5c 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -51,6 +51,7 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
public static final int FLAG_ACTIVITY_SENDER = 1 << 0;
public static final int FLAG_BROADCAST_SENDER = 1 << 1;
+ public static final int FLAG_SERVICE_SENDER = 1 << 2;
final PendingIntentController controller;
final Key key;
@@ -62,6 +63,7 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
private ArraySet<IBinder> mAllowBgActivityStartsForActivitySender = new ArraySet<>();
private ArraySet<IBinder> mAllowBgActivityStartsForBroadcastSender = new ArraySet<>();
+ private ArraySet<IBinder> mAllowBgActivityStartsForServiceSender = new ArraySet<>();
String stringName;
String lastTagPrefix;
@@ -228,6 +230,9 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
if ((flags & FLAG_BROADCAST_SENDER) != 0) {
mAllowBgActivityStartsForBroadcastSender.add(token);
}
+ if ((flags & FLAG_SERVICE_SENDER) != 0) {
+ mAllowBgActivityStartsForServiceSender.add(token);
+ }
}
public void registerCancelListenerLocked(IResultReceiver receiver) {
@@ -426,7 +431,8 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
try {
controller.mAmInternal.startServiceInPackage(uid, finalIntent, resolvedType,
key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
- key.packageName, userId);
+ key.packageName, userId,
+ mAllowBgActivityStartsForServiceSender.contains(whitelistToken));
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startService intent", e);
} catch (TransactionTooLargeException e) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 0d0824a74cdd..054c83080d98 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1142,11 +1142,13 @@ final class ProcessRecord implements WindowProcessListener {
}
void addAllowBackgroundActivityStartsToken(Binder entity) {
+ if (entity == null) return;
mAllowBackgroundActivityStartsTokens.add(entity);
mWindowProcessController.setAllowBackgroundActivityStarts(true);
}
void removeAllowBackgroundActivityStartsToken(Binder entity) {
+ if (entity == null) return;
mAllowBackgroundActivityStartsTokens.remove(entity);
mWindowProcessController.setAllowBackgroundActivityStarts(
!mAllowBackgroundActivityStartsTokens.isEmpty());
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c68e0f98325e..7ecdad27c505 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -77,6 +77,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
+import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER;
import static com.android.server.utils.PriorityDump.PRIORITY_ARG;
import static com.android.server.utils.PriorityDump.PRIORITY_ARG_CRITICAL;
import static com.android.server.utils.PriorityDump.PRIORITY_ARG_NORMAL;
@@ -4452,7 +4453,8 @@ public class NotificationManagerService extends SystemService {
am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(),
WHITELIST_TOKEN, duration);
am.setPendingIntentAllowBgActivityStarts(pendingIntent.getTarget(),
- WHITELIST_TOKEN, (FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER));
+ WHITELIST_TOKEN, (FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER
+ | FLAG_SERVICE_SENDER));
}
}
}