Allow holders of SYSTEM_ALERT_WINDOW permission to start
activities from background

Bug: 130222474
Test: manual, seeing log:
mkarpinski@mkarpinski2:~/android/qt-dev$ adb logcat -b system | grep "allowed because SYSTEM"
04-26 15:55:41.761  1283  3067 W ActivityTaskManager: Background activity start for com.facebook.orca allowed because SYSTEM_ALERT_WINDOW permission is granted.
Change-Id: I7d0a2ae7fde9b1f7f96a4936d872397a7e07ce0e
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 4ef8753..6976aa9 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1038,6 +1038,12 @@
                 }
             }
         }
+        // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
+        if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
+            Slog.w(TAG, "Background activity start for " + callingPackage
+                    + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
+            return false;
+        }
         // anything that has fallen through would currently be aborted
         Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
                 + "; callingUid: " + callingUid
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 7bc9600..4a6aa33 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -108,12 +108,10 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_ACTIVITY_ID;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_TASK_ID;
 import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
 import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
@@ -136,6 +134,7 @@
 import android.app.ActivityThread;
 import android.app.AlertDialog;
 import android.app.AppGlobals;
+import android.app.AppOpsManager;
 import android.app.Dialog;
 import android.app.IActivityController;
 import android.app.IActivityTaskManager;
@@ -216,7 +215,6 @@
 import android.util.ArrayMap;
 import android.util.EventLog;
 import android.util.Log;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
@@ -875,6 +873,16 @@
         return getUserManager().hasUserRestriction(restriction, userId);
     }
 
+    boolean hasSystemAlertWindowPermission(int callingUid, int callingPid, String callingPackage) {
+        final int mode = getAppOpsService().noteOperation(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+                callingUid, callingPackage);
+        if (mode == AppOpsManager.MODE_DEFAULT) {
+            return checkPermission(Manifest.permission.SYSTEM_ALERT_WINDOW, callingPid, callingUid)
+                    == PERMISSION_GRANTED;
+        }
+        return mode == AppOpsManager.MODE_ALLOWED;
+    }
+
     protected RecentTasks createRecentTasks() {
         return new RecentTasks(this, mStackSupervisor);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index afd4ec1..2991dff 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -41,6 +41,7 @@
 
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
+import android.app.AppOpsManager;
 import android.app.IApplicationThread;
 import android.content.ComponentName;
 import android.content.Context;
@@ -413,12 +414,18 @@
         ActivityStackSupervisor mTestStackSupervisor;
 
         ActivityDisplay mDefaultDisplay;
+        AppOpsService mAppOpsService;
 
         TestActivityTaskManagerService(Context context) {
             super(context);
             spyOn(this);
 
             mUgmInternal = mock(UriGrantsManagerInternal.class);
+            mAppOpsService = mock(AppOpsService.class);
+
+            // Make sure permission checks aren't overridden.
+            doReturn(AppOpsManager.MODE_DEFAULT)
+                    .when(mAppOpsService).noteOperation(anyInt(), anyInt(), anyString());
 
             mSupportsMultiWindow = true;
             mSupportsMultiDisplay = true;
@@ -482,6 +489,11 @@
         }
 
         @Override
+        AppOpsService getAppOpsService() {
+            return mAppOpsService;
+        }
+
+        @Override
         void updateCpuStats() {
         }