OSDN Git Service

Kill foreground apps when turning off work
authorRubin Xu <rubinxu@google.com>
Fri, 1 Apr 2016 14:50:58 +0000 (15:50 +0100)
committerRubin Xu <rubinxu@google.com>
Tue, 19 Apr 2016 13:23:33 +0000 (14:23 +0100)
While work apps will all be killed as we stop the profile user when
turning off work, this can sometimes take a while. So let's kill the
foreground apps as soon as work profile is being turned off to make
the user experience nicer.

Bug: 27631526
Change-Id: Icdd3799385a98ee531b0b4247e8ede78f6f10da8

core/java/android/app/ActivityManagerInternal.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/pm/UserManagerService.java

index ee4c2f7..4b8d9ee 100644 (file)
@@ -139,4 +139,9 @@ public abstract class ActivityManagerInternal {
      * minimized state.
      */
     public abstract void notifyDockedStackMinimizedChanged(boolean minimized);
+
+    /**
+     * Kill foreground apps from the specified user.
+     */
+    public abstract void killForegroundAppsForUser(int userHandle);
 }
index a60690c..359e3a3 100644 (file)
@@ -20980,6 +20980,36 @@ public final class ActivityManagerService extends ActivityManagerNative
                 mStackSupervisor.setDockedStackMinimized(minimized);
             }
         }
+
+        @Override
+        public void killForegroundAppsForUser(int userHandle) {
+            synchronized (ActivityManagerService.this) {
+                final ArrayList<ProcessRecord> procs = new ArrayList<>();
+                final int NP = mProcessNames.getMap().size();
+                for (int ip = 0; ip < NP; ip++) {
+                    final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+                    final int NA = apps.size();
+                    for (int ia = 0; ia < NA; ia++) {
+                        final ProcessRecord app = apps.valueAt(ia);
+                        if (app.persistent) {
+                            // We don't kill persistent processes.
+                            continue;
+                        }
+                        if (app.removed) {
+                            procs.add(app);
+                        } else if (app.userId == userHandle && app.foregroundActivities) {
+                            app.removed = true;
+                            procs.add(app);
+                        }
+                    }
+                }
+
+                final int N = procs.size();
+                for (int i = 0; i < N; i++) {
+                    removeProcessLocked(procs.get(i), false, true, "kill all fg");
+                }
+            }
+        }
     }
 
     private final class SleepTokenImpl extends SleepToken {
index 42f7166..8a889e0 100644 (file)
@@ -667,6 +667,8 @@ public class UserManagerService extends IUserManager.Stub {
             long identity = Binder.clearCallingIdentity();
             try {
                 if (enableQuietMode) {
+                    LocalServices.getService(ActivityManagerInternal.class)
+                            .killForegroundAppsForUser(userHandle);
                     ActivityManagerNative.getDefault().stopUser(userHandle, /* force */true, null);
                 } else {
                     ActivityManagerNative.getDefault().startUserInBackground(userHandle);