Fix issue #7211769 and #7244492, thrash around on #7226656.

Issue #7211769: Crash dialog from background user has non-working "report"

The report button now launches the issue reporter for the correct user.
Also for crashes on background users, either disable the report button,
or simply don't show the dialog depending on the build config.

Issue #7244492: Bugreport button in Quick Settings doesn't actually do anything

Now they do.

Issue #7226656: second user seeing primary user's apps

I haven't had any success at reproducing this.  I have tried to tighten up
the path where we create the user to ensure nothing could cause the
user's applications to be accessed before the user it fully created and thus
make them installed...  but I can't convince myself that is the actual problem.

Also tightened up the user switch code to use forground broadcasts for all
of the updates about the switch (since this is really a foreground operation),
added a facility to have BOOT_COMPELTED broadcasts not get launched for
secondary users and use that on a few key system receivers, fixed some debug
output.

Change-Id: Iadf8f8e4878a86def2e495e9d0dc40c4fb347021
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index bfefe67..2db0f97 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -912,21 +912,38 @@
             switch (msg.what) {
             case SHOW_ERROR_MSG: {
                 HashMap data = (HashMap) msg.obj;
+                boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
+                        Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
                 synchronized (ActivityManagerService.this) {
                     ProcessRecord proc = (ProcessRecord)data.get("app");
+                    AppErrorResult res = (AppErrorResult) data.get("result");
                     if (proc != null && proc.crashDialog != null) {
                         Slog.e(TAG, "App already has crash dialog: " + proc);
+                        if (res != null) {
+                            res.set(0);
+                        }
                         return;
                     }
-                    AppErrorResult res = (AppErrorResult) data.get("result");
+                    if (!showBackground && UserHandle.getAppId(proc.uid)
+                            >= Process.FIRST_APPLICATION_UID && proc.userId != mCurrentUserId
+                            && proc.pid != MY_PID) {
+                        Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
+                        if (res != null) {
+                            res.set(0);
+                        }
+                        return;
+                    }
                     if (mShowDialogs && !mSleeping && !mShuttingDown) {
-                        Dialog d = new AppErrorDialog(mContext, res, proc);
+                        Dialog d = new AppErrorDialog(mContext,
+                                ActivityManagerService.this, res, proc);
                         d.show();
                         proc.crashDialog = d;
                     } else {
                         // The device is asleep, so just pretend that the user
                         // saw a crash dialog and hit "force quit".
-                        res.set(0);
+                        if (res != null) {
+                            res.set(0);
+                        }
                     }
                 }
                 
@@ -977,7 +994,8 @@
                     }
                     AppErrorResult res = (AppErrorResult) data.get("result");
                     if (mShowDialogs && !mSleeping && !mShuttingDown) {
-                        Dialog d = new StrictModeViolationDialog(mContext, res, proc);
+                        Dialog d = new StrictModeViolationDialog(mContext,
+                                ActivityManagerService.this, res, proc);
                         d.show();
                         proc.crashDialog = d;
                     } else {
@@ -3683,7 +3701,8 @@
 
     void closeSystemDialogsLocked(String reason) {
         Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                | Intent.FLAG_RECEIVER_FOREGROUND);
         if (reason != null) {
             intent.putExtra("reason", reason);
         }
@@ -3755,7 +3774,8 @@
         Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
                 Uri.fromParts("package", packageName, null));
         if (!mProcessesReady) {
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                    | Intent.FLAG_RECEIVER_FOREGROUND);
         }
         intent.putExtra(Intent.EXTRA_UID, uid);
         intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
@@ -3768,7 +3788,8 @@
     private void forceStopUserLocked(int userId) {
         forceStopPackageLocked(null, -1, false, false, true, false, userId);
         Intent intent = new Intent(Intent.ACTION_USER_STOPPED);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                | Intent.FLAG_RECEIVER_FOREGROUND);
         intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
         broadcastIntentLocked(null, null, intent,
                 null, null, 0, null, null, null,
@@ -7363,7 +7384,14 @@
             return mController != null;
         }
     }
-    
+
+    public void requestBugReport() {
+        // No permission check because this can't do anything harmful --
+        // it will just eventually cause the user to be presented with
+        // a UI to select where the bug report goes.
+        SystemProperties.set("ctl.start", "bugreport");
+    }
+
     public void registerProcessObserver(IProcessObserver observer) {
         enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                 "registerProcessObserver()");
@@ -7698,9 +7726,9 @@
                         }
                     }
                     intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
-                    
+
                     ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
-                    
+
                     final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
                     for (int i=0; i<ris.size(); i++) {
                         ActivityInfo ai = ris.get(i).activityInfo;
@@ -7874,7 +7902,8 @@
             long ident = Binder.clearCallingIdentity();
             try {
                 Intent intent = new Intent(Intent.ACTION_USER_STARTED);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
                 broadcastIntentLocked(null, null, intent,
                         null, null, 0, null, null, null,
@@ -8081,8 +8110,15 @@
     }
 
     void startAppProblemLocked(ProcessRecord app) {
-        app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
-                mContext, app.info.packageName, app.info.flags);
+        if (app.userId == mCurrentUserId) {
+            app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
+                    mContext, app.info.packageName, app.info.flags);
+        } else {
+            // If this app is not running under the current user, then we
+            // can't give it a report button because that would require
+            // launching the report UI under a different user.
+            app.errorReportReceiver = null;
+        }
         skipCurrentReceiverLocked(app);
     }
 
@@ -8590,7 +8626,7 @@
 
         if (appErrorIntent != null) {
             try {
-                mContext.startActivity(appErrorIntent);
+                mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
             } catch (ActivityNotFoundException e) {
                 Slog.w(TAG, "bug report receiver dissappeared", e);
             }
@@ -11427,6 +11463,17 @@
             for (int user : users) {
                 List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                         .queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
+                if (user != 0 && newReceivers != null) {
+                    // If this is not the primary user, we need to check for
+                    // any receivers that should be filtered out.
+                    for (int i=0; i<newReceivers.size(); i++) {
+                        ResolveInfo ri = newReceivers.get(i);
+                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_PRIMARY_USER_ONLY) != 0) {
+                            newReceivers.remove(i);
+                            i--;
+                        }
+                    }
+                }
                 if (newReceivers != null && newReceivers.size() == 0) {
                     newReceivers = null;
                 }
@@ -12271,12 +12318,14 @@
                 }
                 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
-                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);
+                        | Intent.FLAG_RECEIVER_REPLACE_PENDING
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
                 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
                         null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
                 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
-                    broadcastIntentLocked(null, null,
-                            new Intent(Intent.ACTION_LOCALE_CHANGED),
+                    intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
+                    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                    broadcastIntentLocked(null, null, intent,
                             null, null, 0, null, null,
                             null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
                 }
@@ -14084,7 +14133,8 @@
                 mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG,
                         oldUserId, userId, uss), USER_SWITCH_TIMEOUT);
                 Intent intent = new Intent(Intent.ACTION_USER_STARTED);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
                 broadcastIntentLocked(null, null, intent,
                         null, null, 0, null, null, null,
@@ -14093,17 +14143,17 @@
                 if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
                     if (userId != 0) {
                         intent = new Intent(Intent.ACTION_USER_INITIALIZE);
+                        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                         broadcastIntentLocked(null, null, intent, null,
                                 new IIntentReceiver.Stub() {
                                     public void performReceive(Intent intent, int resultCode,
                                             String data, Bundle extras, boolean ordered,
                                             boolean sticky, int sendingUser) {
-                                        synchronized (ActivityManagerService.this) {
-                                            getUserManagerLocked().makeInitialized(userInfo.id);
-                                        }
+                                        userInitialized(uss);
                                     }
                                 }, 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
                                 userId);
+                        uss.initializing = true;
                     } else {
                         getUserManagerLocked().makeInitialized(userInfo.id);
                     }
@@ -14130,7 +14180,8 @@
             Intent intent;
             if (oldUserId >= 0) {
                 intent = new Intent(Intent.ACTION_USER_BACKGROUND);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, oldUserId);
                 broadcastIntentLocked(null, null, intent,
                         null, null, 0, null, null, null,
@@ -14138,13 +14189,15 @@
             }
             if (newUserId >= 0) {
                 intent = new Intent(Intent.ACTION_USER_FOREGROUND);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
                 broadcastIntentLocked(null, null, intent,
                         null, null, 0, null, null, null,
                         false, false, MY_PID, Process.SYSTEM_UID, newUserId);
                 intent = new Intent(Intent.ACTION_USER_SWITCHED);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
                 broadcastIntentLocked(null, null, intent,
                         null, null, 0, null, null,
@@ -14175,6 +14228,7 @@
                 }
             };
             synchronized (this) {
+                uss.switching = true;
                 mCurUserSwitchCallback = callback;
             }
             for (int i=0; i<N; i++) {
@@ -14206,6 +14260,14 @@
                 oldUserId, newUserId, uss));
     }
 
+    void userInitialized(UserStartedState uss) {
+        synchronized (ActivityManagerService.this) {
+            getUserManagerLocked().makeInitialized(uss.mHandle.getIdentifier());
+            uss.initializing = false;
+            completeSwitchAndInitalizeLocked(uss);
+        }
+    }
+
     void continueUserSwitch(UserStartedState uss, int oldUserId, int newUserId) {
         final int N = mUserSwitchObservers.beginBroadcast();
         for (int i=0; i<N; i++) {
@@ -14216,6 +14278,13 @@
         }
         mUserSwitchObservers.finishBroadcast();
         synchronized (this) {
+            uss.switching = false;
+            completeSwitchAndInitalizeLocked(uss);
+        }
+    }
+
+    void completeSwitchAndInitalizeLocked(UserStartedState uss) {
+        if (!uss.switching && !uss.initializing) {
             mWindowManager.stopFreezingScreen();
         }
     }