OSDN Git Service

Allow apps that are currently instrumenting with background activity
authorMichal Karpinski <mkarpinski@google.com>
Tue, 29 Jan 2019 16:50:51 +0000 (16:50 +0000)
committerMichal Karpinski <mkarpinski@google.com>
Wed, 30 Jan 2019 14:21:08 +0000 (14:21 +0000)
starts privileges to start activities from background

Test: atest WmTests:ActivityStarterTests
Test: atest google/perf/jank/SystemUI/UbSystemUIJankTests
Test: atest LightBarTests
Test: atest CtsActivityManagerDeviceTestCases
Bug: 123434182
Bug: 110956953
Bug: 122760822
Change-Id: I66dc700bcb4713838528094a35337bcb3770d229

services/core/java/com/android/server/am/ActiveInstrumentation.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ProcessRecord.java
services/core/java/com/android/server/wm/ActivityStarter.java
services/core/java/com/android/server/wm/WindowProcessController.java
services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java

index 15de3de..9510f59 100644 (file)
@@ -49,6 +49,9 @@ class ActiveInstrumentation {
     // Connection to use the UI introspection APIs.
     IUiAutomationConnection mUiAutomationConnection;
 
+    // Whether the caller holds START_ACTIVITIES_FROM_BACKGROUND permission
+    boolean mHasBackgroundActivityStartsPermission;
+
     // As given to us
     Bundle mArguments;
 
@@ -117,6 +120,8 @@ class ActiveInstrumentation {
             pw.print(prefix); pw.print("mUiAutomationConnection=");
             pw.println(mUiAutomationConnection);
         }
+        pw.print("mHasBackgroundActivityStartsPermission=");
+        pw.println(mHasBackgroundActivityStartsPermission);
         pw.print(prefix); pw.print("mArguments=");
         pw.println(mArguments);
     }
index d9f3c02..a1dc958 100644 (file)
@@ -22,6 +22,7 @@ import static android.Manifest.permission.FILTER_EVENTS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.Manifest.permission.REMOVE_TASKS;
+import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
 import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
 import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
 import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
@@ -15194,7 +15195,9 @@ public class ActivityManagerService extends IActivityManager.Stub
             IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection,
             int userId, String abiOverride) {
         enforceNotIsolatedCaller("startInstrumentation");
-        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+        final int callingUid = Binder.getCallingUid();
+        final int callingPid = Binder.getCallingPid();
+        userId = mUserController.handleIncomingUser(callingPid, callingUid,
                 userId, false, ALLOW_FULL_ONLY, "startInstrumentation", null);
         // Refuse possible leaked file descriptors
         if (arguments != null && arguments.hasFileDescriptors()) {
@@ -15259,6 +15262,9 @@ public class ActivityManagerService extends IActivityManager.Stub
             activeInstr.mWatcher = watcher;
             activeInstr.mUiAutomationConnection = uiAutomationConnection;
             activeInstr.mResultClass = className;
+            activeInstr.mHasBackgroundActivityStartsPermission = checkPermission(
+                    START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
+                            == PackageManager.PERMISSION_GRANTED;
 
             boolean disableHiddenApiChecks = ai.usesNonSdkApi()
                     || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
index 054c830..ec359f4 100644 (file)
@@ -1157,6 +1157,8 @@ final class ProcessRecord implements WindowProcessListener {
     void setActiveInstrumentation(ActiveInstrumentation instr) {
         mInstr = instr;
         mWindowProcessController.setInstrumenting(instr != null);
+        mWindowProcessController.setInstrumentingWithBackgroundActivityStartPrivileges(instr != null
+                && instr.mHasBackgroundActivityStartsPermission);
     }
 
     ActiveInstrumentation getActiveInstrumentation() {
index 95a6f71..d1cd1db 100644 (file)
@@ -926,6 +926,10 @@ class ActivityStarter {
         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 =
index 07f26b4..6fb6c2c 100644 (file)
@@ -138,6 +138,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
     private volatile boolean mDebugging;
     // Active instrumentation running in process?
     private volatile boolean mInstrumenting;
+    // Active instrumentation with background activity starts privilege running in process?
+    private volatile boolean mInstrumentingWithBackgroundActivityStartPrivileges;
     // This process it perceptible by the user.
     private volatile boolean mPerceptible;
     // Set to true when process was launched with a wrapper attached
@@ -370,6 +372,23 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
         return mInstrumenting;
     }
 
+    /**
+     * {@see isInstrumentingWithBackgroundActivityStartPrivileges}
+     */
+    public void setInstrumentingWithBackgroundActivityStartPrivileges(
+            boolean instrumentingWithBackgroundActivityStartPrivileges) {
+        mInstrumentingWithBackgroundActivityStartPrivileges =
+                instrumentingWithBackgroundActivityStartPrivileges;
+    }
+
+    /**
+     * @return true if the instrumentation was started by a holder of
+     * START_ACTIVITIES_FROM_BACKGROUND permission
+     */
+    boolean isInstrumentingWithBackgroundActivityStartPrivileges() {
+        return mInstrumentingWithBackgroundActivityStartPrivileges;
+    }
+
     public void setPerceptible(boolean perceptible) {
         mPerceptible = perceptible;
     }
index ace965b..62ec838 100644 (file)
@@ -561,7 +561,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
         runAndVerifyBackgroundActivityStartsSubtest("allowed_noStartsAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
     }
 
     /**
@@ -576,7 +576,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
                 "disallowed_unsupportedUsecase_aborted", true,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
     }
 
     /**
@@ -591,57 +591,64 @@ public class ActivityStarterTests extends ActivityTestsBase {
         runAndVerifyBackgroundActivityStartsSubtest("disallowed_rootUid_notAborted", false,
                 Process.ROOT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest("disallowed_systemUid_notAborted", false,
                 Process.SYSTEM_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest("disallowed_nfcUid_notAborted", false,
                 Process.NFC_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callingUidHasVisibleWindow_notAborted", false,
                 UNIMPORTANT_UID, true, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callingUidProcessStateTop_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_realCallingUidHasVisibleWindow_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, true, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_realCallingUidProcessStateTop_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_hasForegroundActivities_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                true, false, false);
+                true, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callerIsRecents_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, true, false);
+                false, true, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callerIsWhitelisted_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, true);
+                false, false, true, false);
+        runAndVerifyBackgroundActivityStartsSubtest(
+                "disallowed_callerIsInstrumentingWithBackgroundActivityStartPrivileges_notAborted",
+                false,
+                UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+                UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+                false, false, false, true);
     }
 
     private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
             int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState,
             int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState,
             boolean hasForegroundActivities, boolean callerIsRecents,
-            boolean callerIsTempWhitelisted) {
+            boolean callerIsTempWhitelisted,
+            boolean callerIsInstrumentingWithBackgroundActivityStartPrivileges) {
         // window visibility
         doReturn(callingUidHasVisibleWindow).when(mService.mWindowManager.mRoot)
                 .isAnyNonToastWindowVisibleForUid(callingUid);
@@ -664,6 +671,9 @@ public class ActivityStarterTests extends ActivityTestsBase {
         doReturn(callerIsRecents).when(recentTasks).isCallerRecents(callingUid);
         // caller is temp whitelisted
         callerApp.setAllowBackgroundActivityStarts(callerIsTempWhitelisted);
+        // caller is instrumenting with background activity starts privileges
+        callerApp.setInstrumentingWithBackgroundActivityStartPrivileges(
+                callerIsInstrumentingWithBackgroundActivityStartPrivileges);
 
         final ActivityOptions options = spy(ActivityOptions.makeBasic());
         ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)