Merge "Introduced WindowProcessController/Listener (10/n)"
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 2fdb715..e5cfe84 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.app.IVoiceInteractor;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -204,4 +205,12 @@
 
     /** Closes all system dialogs. */
     public abstract void closeSystemDialogs(String reason);
+
+    /** Kill the processes in the list due to their tasks been removed. */
+    public abstract void killProcessesForRemovedTask(ArrayList<Object> procsToKill);
+
+    /**
+     * Returns {@code true} if {@code uid} is running an activity from {@code packageName}.
+     */
+    public abstract boolean hasRunningActivity(int uid, @Nullable String packageName);
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 4365760..376d16b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -20,7 +20,6 @@
 import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
-
 import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
@@ -30,8 +29,6 @@
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.app.AlertDialog;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
@@ -112,10 +109,9 @@
 import com.android.internal.util.IntPair;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
-import libcore.util.EmptyArray;
-
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.FileDescriptor;
@@ -134,6 +130,8 @@
 import java.util.function.Consumer;
 import java.util.function.IntSupplier;
 
+import libcore.util.EmptyArray;
+
 /**
  * This class is instantiated by the system as a system level service and can be
  * accessed only by the system. The task of this service is to be a centralized
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index a2dc986..4206d9a 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -28,7 +28,6 @@
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
 import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
@@ -83,6 +82,7 @@
 import com.android.server.LocalServices;
 import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
 import com.android.server.autofill.ui.AutoFillUI;
+import com.android.server.wm.ActivityTaskManagerInternal;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -534,7 +534,7 @@
         } catch (NameNotFoundException e) {
             throw new SecurityException("Could not verify UID for " + componentName);
         }
-        if (callingUid != packageUid && !LocalServices.getService(ActivityTaskManagerInternal.class)
+        if (callingUid != packageUid && !LocalServices.getService(ActivityManagerInternal.class)
                 .hasRunningActivity(callingUid, packageName)) {
             final String[] packages = pm.getPackagesForUid(callingUid);
             final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid;
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 48f27d8..18255c5 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -16,8 +16,6 @@
 
 package com.android.server.autofill;
 
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
 import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
@@ -33,6 +31,8 @@
 import static com.android.server.autofill.Helper.sVerbose;
 import static com.android.server.autofill.Helper.toArray;
 import static com.android.server.autofill.ViewState.STATE_RESTARTED_SESSION;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 4e700d7..a34c2b9 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -19,7 +19,6 @@
 import android.Manifest;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -31,15 +30,15 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.ContentObserver;
 import android.hardware.Sensor;
-import android.hardware.SensorManager;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
 import android.hardware.TriggerEvent;
 import android.hardware.TriggerEventListener;
-import android.location.LocationRequest;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
+import android.location.LocationRequest;
 import android.net.ConnectivityManager;
 import android.net.INetworkPolicyManager;
 import android.net.NetworkInfo;
@@ -86,6 +85,7 @@
 import com.android.internal.util.XmlUtils;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d025a87..92005d2 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -24,23 +24,18 @@
 import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
 import static android.os.storage.OnObbStateChangeListener.MOUNTED;
 import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
-
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
 import static com.android.internal.util.XmlUtils.readStringAttribute;
 import static com.android.internal.util.XmlUtils.writeIntAttribute;
 import static com.android.internal.util.XmlUtils.writeLongAttribute;
 import static com.android.internal.util.XmlUtils.writeStringAttribute;
-
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
 import android.Manifest;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
-import android.app.ActivityTaskManagerInternal.ScreenObserver;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.KeyguardManager;
@@ -126,9 +121,8 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.storage.AppFuseBridge;
-
-import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
+import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -164,6 +158,9 @@
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
 
+import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
+
 /**
  * Service responsible for various storage media. Connects to {@code vold} to
  * watch for and manage dynamically added storage, such as SD cards and USB mass
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 652bc6a..f7cd5ad 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1389,7 +1389,7 @@
     private boolean updateServiceClientActivitiesLocked(ProcessRecord proc,
             ConnectionRecord modCr, boolean updateLru) {
         if (modCr != null && modCr.binding.client != null) {
-            if (modCr.binding.client.activities.size() <= 0) {
+            if (!modCr.binding.client.hasActivities()) {
                 // This connection is from a client without activities, so adding
                 // and removing is not interesting.
                 return false;
@@ -1407,7 +1407,7 @@
                         // Binding to ourself is not interesting.
                         continue;
                     }
-                    if (cr.binding.client.activities.size() > 0) {
+                    if (cr.binding.client.hasActivities()) {
                         anyClientActivities = true;
                         break;
                     }
@@ -2081,7 +2081,7 @@
                 bumpServiceExecutingLocked(r, execInFg, "bind");
                 r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
-                        r.app.repProcState);
+                        r.app.getReportedProcState());
                 if (!rebind) {
                     i.requested = true;
                 }
@@ -2463,7 +2463,7 @@
             app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
             app.thread.scheduleCreateService(r, r.serviceInfo,
                     mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
-                    app.repProcState);
+                    app.getReportedProcState());
             r.postNotification();
             created = true;
         } catch (DeadObjectException e) {
@@ -3050,7 +3050,7 @@
                 }
             }
             if (finishing) {
-                if (r.app != null && !r.app.persistent) {
+                if (r.app != null && !r.app.isPersistent()) {
                     r.app.services.remove(r);
                     if (r.whitelistManager) {
                         updateWhitelistManagerLocked(r.app);
@@ -3140,7 +3140,7 @@
                         && (filterByClasses == null
                             || filterByClasses.contains(service.name.getClassName())));
             if (sameComponent
-                    && (service.app == null || evenPersistent || !service.app.persistent)) {
+                    && (service.app == null || evenPersistent || !service.app.isPersistent())) {
                 if (!doit) {
                     return true;
                 }
@@ -3148,7 +3148,7 @@
                 Slog.i(TAG, "  Force stopping service " + service);
                 if (service.app != null) {
                     service.app.removed = killProcess;
-                    if (!service.app.persistent) {
+                    if (!service.app.isPersistent()) {
                         service.app.services.remove(service);
                         if (service.whitelistManager) {
                             updateWhitelistManagerLocked(service.app);
@@ -3302,7 +3302,7 @@
             synchronized (sr.stats.getBatteryStats()) {
                 sr.stats.stopLaunchedLocked();
             }
-            if (sr.app != app && sr.app != null && !sr.app.persistent) {
+            if (sr.app != app && sr.app != null && !sr.app.isPersistent()) {
                 sr.app.services.remove(sr);
             }
             sr.app = null;
@@ -3347,7 +3347,7 @@
                         continue;
                     }
                     // XXX turned off for now until we have more time to get a better policy.
-                    if (false && proc != null && !proc.persistent && proc.thread != null
+                    if (false && proc != null && !proc.isPersistent() && proc.thread != null
                             && proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID
                             && proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                         proc.kill("bound to service " + sr.name.flattenToShortString()
@@ -3365,7 +3365,7 @@
 
             // Unless the process is persistent, this process record is going away,
             // so make sure the service is cleaned out of it.
-            if (!app.persistent) {
+            if (!app.isPersistent()) {
                 app.services.removeAt(i);
             }
 
@@ -3475,7 +3475,7 @@
         if (r.app != null && r.app.pid == ActivityManagerService.MY_PID) {
             info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
         }
-        if (r.app != null && r.app.persistent) {
+        if (r.app != null && r.app.isPersistent()) {
             info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 5608f97..9f9fe4c 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -30,28 +30,29 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.FLAG_PRIVATE;
 import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
+import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityDisplayProto.ID;
+import static com.android.server.am.ActivityDisplayProto.STACKS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityDisplayProto.STACKS;
-import static com.android.server.am.ActivityDisplayProto.ID;
 
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
-import android.app.ActivityTaskManagerInternal;
 import android.app.WindowConfiguration;
 import android.graphics.Point;
 import android.util.IntArray;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
+
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.ConfigurationContainer;
 import com.android.server.wm.DisplayWindowController;
-
 import com.android.server.wm.WindowContainerListener;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1c61f30..70901d0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -22,6 +22,8 @@
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
 import static android.Manifest.permission.REMOVE_TASKS;
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
+import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
 import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
@@ -30,10 +32,6 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
 import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
-import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
-import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
-import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
-import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.GET_PROVIDERS;
 import static android.content.pm.PackageManager.MATCH_ANY_USER;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
@@ -42,10 +40,8 @@
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
 import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
 import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
-import static android.os.Build.VERSION_CODES.N;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
@@ -67,7 +63,6 @@
 import static android.os.Process.SCHED_RESET_ON_FORK;
 import static android.os.Process.SE_UID;
 import static android.os.Process.SHELL_UID;
-import static android.os.Process.SIGNAL_QUIT;
 import static android.os.Process.SIGNAL_USR1;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.THREAD_GROUP_BG_NONINTERACTIVE;
@@ -94,16 +89,12 @@
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
 import static android.provider.Settings.Global.DEBUG_APP;
-import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
-import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
-import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
 import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
 import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
 import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
 import static android.provider.Settings.System.FONT_SCALE;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.INVALID_DISPLAY;
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
@@ -141,8 +132,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IMMERSIVE;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LRU;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
@@ -153,18 +142,15 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PROCESS_OBSERVERS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PROVIDER;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PSS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_URI_PERMISSION;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 import static com.android.server.am.MemoryStatUtil.hasMemcg;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
@@ -177,14 +163,9 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManager.StackInfo;
-import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
-import android.app.ActivityTaskManagerInternal.ScreenObserver;
-import android.app.ActivityTaskManagerInternal.SleepToken;
 import android.app.ActivityManagerProto;
 import android.app.ActivityOptions;
-import android.app.ActivityTaskManager;
 import android.app.ActivityThread;
 import android.app.AlertDialog;
 import android.app.AppGlobals;
@@ -217,7 +198,6 @@
 import android.app.WindowConfiguration.ActivityType;
 import android.app.WindowConfiguration.WindowingMode;
 import android.app.backup.IBackupManager;
-import android.app.servertransaction.ConfigurationChangeItem;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
@@ -272,7 +252,6 @@
 import android.os.DropBoxManager;
 import android.os.Environment;
 import android.os.FactoryTest;
-import android.os.FileObserver;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder;
@@ -280,7 +259,6 @@
 import android.os.IPermissionController;
 import android.os.IProcessInfoService;
 import android.os.IProgressListener;
-import android.os.LocaleList;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
@@ -311,7 +289,6 @@
 import android.service.voice.IVoiceInteractionSession;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
-import android.text.format.Time;
 import android.text.style.SuggestionSpan;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -338,6 +315,9 @@
 import android.view.WindowManager;
 import android.view.autofill.AutofillManagerInternal;
 
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -382,17 +362,17 @@
 import com.android.server.SystemServiceManager;
 import com.android.server.ThreadPriorityBooster;
 import com.android.server.Watchdog;
-import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.am.MemoryStatUtil.MemoryStat;
-import com.android.server.am.ActivityManagerServiceProto;
 import com.android.server.am.ActivityManagerServiceDumpActivitiesProto;
 import com.android.server.am.ActivityManagerServiceDumpBroadcastsProto;
 import com.android.server.am.ActivityManagerServiceDumpProcessesProto;
 import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
 import com.android.server.am.ActivityManagerServiceDumpServicesProto;
+import com.android.server.am.ActivityManagerServiceProto;
+import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.am.GrantUriProto;
 import com.android.server.am.ImportanceTokenProto;
 import com.android.server.am.MemInfoDumpProto;
+import com.android.server.am.MemoryStatUtil.MemoryStat;
 import com.android.server.am.NeededUriGrantsProto;
 import com.android.server.am.ProcessOomProto;
 import com.android.server.am.ProcessToGcProto;
@@ -404,16 +384,10 @@
 import com.android.server.pm.dex.DexManager;
 import com.android.server.utils.PriorityDump;
 import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
 import com.android.server.wm.WindowManagerService;
 
-import dalvik.system.VMRuntime;
-
-import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
-
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -450,6 +424,10 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
+import dalvik.system.VMRuntime;
+import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
+
 public class ActivityManagerService extends IActivityManager.Stub
         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
 
@@ -728,7 +706,22 @@
      * returned by the package manager), and the keys are ApplicationRecord
      * objects.
      */
-    final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
+    final MyProcessMap mProcessNames = new MyProcessMap();
+    final class MyProcessMap extends ProcessMap<ProcessRecord> {
+        @Override
+        public ProcessRecord put(String name, int uid, ProcessRecord value) {
+            final ProcessRecord r = super.put(name, uid, value);
+            mAtmInternal.onProcessAdded(r.getWindowProcessController());
+            return r;
+        }
+
+        @Override
+        public ProcessRecord remove(String name, int uid) {
+            final ProcessRecord r = super.remove(name, uid);
+            mAtmInternal.onProcessRemoved(name, uid);
+            return r;
+        }
+    }
 
     /**
      * Tracking long-term execution of processes to look for abuse and other
@@ -739,7 +732,7 @@
     /**
      * The currently running isolated processes.
      */
-    final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<ProcessRecord>();
+    final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<>();
 
     /**
      * Counter for assigning isolated process uids, to avoid frequently reusing the
@@ -866,23 +859,6 @@
     boolean mFullPssPending = false;
 
     /**
-     * This is the process holding what we currently consider to be
-     * the "home" activity.
-     */
-    ProcessRecord mHomeProcess;
-
-    /**
-     * This is the process holding the activity the user last visited that
-     * is in a different process from the one they are currently in.
-     */
-    ProcessRecord mPreviousProcess;
-
-    /**
-     * The time at which the previous process was last visible.
-     */
-    long mPreviousProcessVisibleTime;
-
-    /**
      * Track all uids that have actively running processes.
      */
     final SparseArray<UidRecord> mActiveUids = new SparseArray<>();
@@ -2048,13 +2024,13 @@
                 }
 
                 ActivityRecord root = (ActivityRecord)msg.obj;
-                ProcessRecord process = root.app;
+                final WindowProcessController process = root.app;
                 if (process == null) {
                     return;
                 }
 
                 try {
-                    Context context = mContext.createPackageContext(process.info.packageName, 0);
+                    Context context = mContext.createPackageContext(process.mInfo.packageName, 0);
                     String text = mContext.getString(R.string.heavy_weight_notification,
                             context.getApplicationInfo().loadLabel(context.getPackageManager()));
                     Notification notification =
@@ -2438,8 +2414,9 @@
 
             synchronized (this) {
                 ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
-                app.persistent = true;
+                app.setPersistent(true);
                 app.pid = MY_PID;
+                app.getWindowProcessController().setPid(MY_PID);
                 app.maxAdj = ProcessList.SYSTEM_ADJ;
                 app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
                 synchronized (mPidsSelfLocked) {
@@ -2475,15 +2452,6 @@
         }
     }
 
-    public void setActivityTaskManager(ActivityTaskManagerService atm) {
-        synchronized (this) {
-            mActivityTaskManager = atm;
-            mActivityTaskManager.setActivityManagerService(this);
-            mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
-            mStackSupervisor = mActivityTaskManager.mStackSupervisor;
-        }
-    }
-
     public void setUsageStatsManager(UsageStatsManagerInternal usageStatsManager) {
         mUsageStatsService = usageStatsManager;
     }
@@ -2584,10 +2552,17 @@
 
     public static final class Lifecycle extends SystemService {
         private final ActivityManagerService mService;
+        private static ActivityTaskManagerService sAtm;
 
         public Lifecycle(Context context) {
             super(context);
-            mService = new ActivityManagerService(context);
+            mService = new ActivityManagerService(context, sAtm);
+        }
+
+        public static ActivityManagerService startService(
+                SystemServiceManager ssm, ActivityTaskManagerService atm) {
+            sAtm = atm;
+            return ssm.startService(ActivityManagerService.Lifecycle.class).getService();
         }
 
         @Override
@@ -2744,7 +2719,7 @@
 
     // Note: This method is invoked on the main thread but may need to attach various
     // handlers to other threads.  So take care to be explicit about the looper.
-    public ActivityManagerService(Context systemContext) {
+    public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
         LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
         mInjector = new Injector();
         mContext = systemContext;
@@ -2823,6 +2798,11 @@
         mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
         mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
 
+        mActivityTaskManager = atm;
+        mActivityTaskManager.setActivityManagerService(this);
+        mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
+        mStackSupervisor = mActivityTaskManager.mStackSupervisor;
+
         mProcessCpuThread = new Thread("CpuTracker") {
             @Override
             public void run() {
@@ -2891,6 +2871,7 @@
         mAppOpsService.publish(mContext);
         Slog.d("AppOps", "AppOpsService published");
         LocalServices.addService(ActivityManagerInternal.class, new LocalService());
+        mActivityTaskManager.onActivityManagerInternalAdded();
         // Wait for the synchronized block started in mProcessCpuThread,
         // so that any other access to mProcessCpuTracker from main thread
         // will be blocked during mProcessCpuTracker initialization.
@@ -3295,7 +3276,7 @@
             String what, Object obj, ProcessRecord srcApp) {
         app.lastActivityTime = now;
 
-        if (app.activities.size() > 0 || app.recentTasks.size() > 0) {
+        if (app.hasActivitiesOrRecentTasks()) {
             // Don't want to touch dependent processes that are hosting activities.
             return index;
         }
@@ -3342,7 +3323,7 @@
         int lrui = mLruProcesses.lastIndexOf(app);
         if (lrui >= 0) {
             if (!app.killed) {
-                if (app.persistent) {
+                if (app.isPersistent()) {
                     Slog.w(TAG, "Removing persistent process that hasn't been killed: " + app);
                 } else {
                     Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
@@ -3366,8 +3347,8 @@
 
     final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
             ProcessRecord client) {
-        final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities
-                || app.treatLikeActivity || app.recentTasks.size() > 0;
+        final boolean hasActivity = app.hasActivitiesOrRecentTasks() || app.hasClientActivities
+                || app.treatLikeActivity;
         final boolean hasService = false; // not impl yet. app.services.size() > 0;
         if (!activityChange && hasActivity) {
             // The process has activities, so we are only allowing activity-based adjustments
@@ -3399,7 +3380,7 @@
 
         int lrui = mLruProcesses.lastIndexOf(app);
 
-        if (app.persistent && lrui >= 0) {
+        if (app.isPersistent() && lrui >= 0) {
             // We don't care about the position of persistent processes, as long as
             // they are in the list.
             if (DEBUG_LRU) Slog.d(TAG_LRU, "Not moving, persistent: " + app);
@@ -3471,7 +3452,7 @@
         int nextIndex;
         if (hasActivity) {
             final int N = mLruProcesses.size();
-            if ((app.activities.size() == 0 || app.recentTasks.size() > 0)
+            if ((!app.hasActivities() || app.hasRecentTasks())
                     && mLruProcessActivityStart < (N - 1)) {
                 // Process doesn't have activities, but has clients with
                 // activities...  move it up, but one below the top (the top
@@ -3546,14 +3527,14 @@
             if (cr.binding != null && !cr.serviceDead && cr.binding.service != null
                     && cr.binding.service.app != null
                     && cr.binding.service.app.lruSeq != mLruSeq
-                    && !cr.binding.service.app.persistent) {
+                    && !cr.binding.service.app.isPersistent()) {
                 nextIndex = updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex,
                         "service connection", cr, app);
             }
         }
         for (int j=app.conProviders.size()-1; j>=0; j--) {
             ContentProviderRecord cpr = app.conProviders.get(j).provider;
-            if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.persistent) {
+            if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.isPersistent()) {
                 nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex,
                         "provider reference", cpr, app);
             }
@@ -3583,7 +3564,7 @@
                 && proc.lastCachedPss >= 4000) {
             // Turn this condition on to cause killing to happen regularly, for testing.
             if (proc.baseProcessTracker != null) {
-                proc.baseProcessTracker.reportCachedKill(proc.pkgList, proc.lastCachedPss);
+                proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss);
             }
             proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
         } else if (proc != null && !keepIfLarge
@@ -3592,7 +3573,7 @@
             if (DEBUG_PSS) Slog.d(TAG_PSS, "May not keep " + proc + ": pss=" + proc.lastCachedPss);
             if (proc.lastCachedPss >= mProcessList.getCachedRestoreThresholdKb()) {
                 if (proc.baseProcessTracker != null) {
-                    proc.baseProcessTracker.reportCachedKill(proc.pkgList, proc.lastCachedPss);
+                    proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss);
                 }
                 proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
             }
@@ -3898,7 +3879,7 @@
             }
 
             if (app.info.isPrivilegedApp() &&
-                    DexManager.isPackageSelectedToRunOob(app.pkgList.keySet())) {
+                    DexManager.isPackageSelectedToRunOob(app.pkgList.mPkgList.keySet())) {
                 runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
             }
 
@@ -3940,7 +3921,7 @@
             }
 
             app.gids = gids;
-            app.requiredAbi = requiredAbi;
+            app.setRequiredAbi(requiredAbi);
             app.instructionSet = instructionSet;
 
             // the per-user SELinux context must be set
@@ -4131,7 +4112,7 @@
             // Ignore
         }
 
-        if (app.persistent) {
+        if (app.isPersistent()) {
             Watchdog.getInstance().processStarted(app.processName, pid);
         }
 
@@ -4190,7 +4171,7 @@
                 "updateUsageStats: comp=" + component + "res=" + resumed);
         final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         StatsLog.write(StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED,
-            component.app.uid, component.realActivity.getPackageName(),
+            component.app.mUid, component.realActivity.getPackageName(),
             component.realActivity.getShortClassName(), resumed ?
                         StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__FOREGROUND :
                         StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__BACKGROUND);
@@ -4201,7 +4182,7 @@
 
             }
             synchronized (stats) {
-                stats.noteActivityResumedLocked(component.app.uid);
+                stats.noteActivityResumedLocked(component.app.mUid);
             }
         } else {
             if (mUsageStatsService != null) {
@@ -4209,7 +4190,7 @@
                         UsageEvents.Event.MOVE_TO_BACKGROUND);
             }
             synchronized (stats) {
-                stats.noteActivityPausedLocked(component.app.uid);
+                stats.noteActivityPausedLocked(component.app.mUid);
             }
         }
     }
@@ -4678,7 +4659,7 @@
 
         // Inform the activity
         try {
-            activityToCallback.app.thread.scheduleLocalVoiceInteractionStarted(activity,
+            activityToCallback.app.getThread().scheduleLocalVoiceInteractionStarted(activity,
                     voiceInteractor);
             long token = Binder.clearCallingIdentity();
             try {
@@ -4746,14 +4727,7 @@
                 return;
             }
 
-            ArrayList<ActivityRecord> activities = new ArrayList<>(proc.activities);
-            for (int i = 0; i < activities.size(); i++) {
-                ActivityRecord r = activities.get(i);
-                if (!r.finishing && r.isInStackLocked()) {
-                    r.getStack().finishActivityLocked(r, Activity.RESULT_CANCELED,
-                            null, "finish-heavy", true);
-                }
-            }
+            proc.getWindowProcessController().finishActivities();
 
             mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
                     proc.userId, 0));
@@ -4802,11 +4776,10 @@
         }
 
         // Remove this application's activities from active lists.
-        boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app);
+        boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app.getWindowProcessController());
 
         app.clearRecentTasks();
-
-        app.activities.clear();
+        app.clearActivities();
 
         if (app.instr != null) {
             Slog.w(TAG, "Crash of app " + app.processName
@@ -4879,7 +4852,7 @@
         for (int i=mLruProcesses.size()-1; i>=0; i--) {
             ProcessRecord rec = mLruProcesses.get(i);
             if (rec.thread != null
-                    && rec.setProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
+                    && rec.setProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                 haveBg = true;
                 break;
             }
@@ -5131,7 +5104,7 @@
         return SystemClock.elapsedRealtime() - timeStart;
     }
 
-    private static void dumpStackTraces(String tracesFile, ArrayList<Integer> firstPids,
+    public static void dumpStackTraces(String tracesFile, ArrayList<Integer> firstPids,
             ArrayList<Integer> nativePids, ArrayList<Integer> extraPids) {
 
         // We don't need any sort of inotify based monitoring when we're dumping traces via
@@ -5207,90 +5180,6 @@
         }
     }
 
-    final void logAppTooSlow(ProcessRecord app, long startTime, String msg) {
-        if (true || Build.IS_USER) {
-            return;
-        }
-
-        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-        StrictMode.allowThreadDiskWrites();
-        try {
-            File tracesDir = new File("/data/anr");
-            File tracesFile = null;
-            try {
-                tracesFile = File.createTempFile("app_slow", null, tracesDir);
-
-                StringBuilder sb = new StringBuilder();
-                Time tobj = new Time();
-                tobj.set(System.currentTimeMillis());
-                sb.append(tobj.format("%Y-%m-%d %H:%M:%S"));
-                sb.append(": ");
-                TimeUtils.formatDuration(SystemClock.uptimeMillis()-startTime, sb);
-                sb.append(" since ");
-                sb.append(msg);
-                FileOutputStream fos = new FileOutputStream(tracesFile);
-                fos.write(sb.toString().getBytes());
-                if (app == null) {
-                    fos.write("\n*** No application process!".getBytes());
-                }
-                fos.close();
-                FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
-            } catch (IOException e) {
-                Slog.w(TAG, "Unable to prepare slow app traces file: " + tracesFile, e);
-                return;
-            }
-
-            if (app != null && app.pid > 0) {
-                ArrayList<Integer> firstPids = new ArrayList<Integer>();
-                firstPids.add(app.pid);
-                dumpStackTraces(tracesFile.getAbsolutePath(), firstPids, null, null);
-            }
-
-            File lastTracesFile = null;
-            File curTracesFile = null;
-            for (int i=9; i>=0; i--) {
-                String name = String.format(Locale.US, "slow%02d.txt", i);
-                curTracesFile = new File(tracesDir, name);
-                if (curTracesFile.exists()) {
-                    if (lastTracesFile != null) {
-                        curTracesFile.renameTo(lastTracesFile);
-                    } else {
-                        curTracesFile.delete();
-                    }
-                }
-                lastTracesFile = curTracesFile;
-            }
-            tracesFile.renameTo(curTracesFile);
-        } finally {
-            StrictMode.setThreadPolicy(oldPolicy);
-        }
-    }
-
-    @GuardedBy("this")
-    final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
-        if (!mLaunchWarningShown) {
-            mLaunchWarningShown = true;
-            mUiHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    synchronized (ActivityManagerService.this) {
-                        final Dialog d = new LaunchWarningWindow(mContext, cur, next);
-                        d.show();
-                        mUiHandler.postDelayed(new Runnable() {
-                            @Override
-                            public void run() {
-                                synchronized (ActivityManagerService.this) {
-                                    d.dismiss();
-                                    mLaunchWarningShown = false;
-                                }
-                            }
-                        }, 4000);
-                    }
-                }
-            });
-        }
-    }
-
     @Override
     public boolean clearApplicationUserData(final String packageName, boolean keepState,
             final IPackageDataObserver observer, int userId) {
@@ -5491,7 +5380,7 @@
                     final int NA = apps.size();
                     for (int ia = 0; ia < NA; ia++) {
                         final ProcessRecord app = apps.valueAt(ia);
-                        if (app.persistent) {
+                        if (app.isPersistent()) {
                             // We don't kill persistent processes.
                             continue;
                         }
@@ -5746,7 +5635,7 @@
                         proc.baseProcessTracker.addPss(infos[i].getTotalPss(),
                                 infos[i].getTotalUss(), infos[i].getTotalRss(), false,
                                 ProcessStats.ADD_PSS_EXTERNAL_SLOW, endTime-startTime,
-                                proc.pkgList);
+                                proc.pkgList.mPkgList);
                     }
                 }
             }
@@ -5776,7 +5665,7 @@
                     if (proc.thread != null && proc.setAdj == oomAdj) {
                         // Record this for posterity if the process has been stable.
                         proc.baseProcessTracker.addPss(pss[i], tmpUss[0], tmpUss[2], false,
-                                ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, proc.pkgList);
+                                ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, proc.pkgList.mPkgList);
                     }
                 }
             }
@@ -5849,7 +5738,7 @@
             final int NA = apps.size();
             for (int ia=0; ia<NA; ia++) {
                 ProcessRecord app = apps.valueAt(ia);
-                if (app.persistent && !evenPersistent) {
+                if (app.isPersistent() && !evenPersistent) {
                     // we don't kill persistent processes
                     continue;
                 }
@@ -6186,7 +6075,7 @@
         // We shouldn't already have a process under this name, but just in case we
         // need to clean up whatever may be there now.
         ProcessRecord old = removeProcessNameLocked(proc.processName, proc.uid);
-        if (old == proc && proc.persistent) {
+        if (old == proc && proc.isPersistent()) {
             // We are re-adding a persistent process.  Whatevs!  Just leave it there.
             Slog.w(TAG, "Re-adding persistent process " + proc);
         } else if (old != null) {
@@ -6253,7 +6142,7 @@
                 }
             }
             boolean willRestart = false;
-            if (app.persistent && !app.isolated) {
+            if (app.isPersistent() && !app.isolated) {
                 if (!callerWillRestart) {
                     willRestart = true;
                 } else {
@@ -6406,7 +6295,7 @@
 
         app.makeActive(thread, mProcessStats);
         app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
-        app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+        app.setCurrentSchedulingGroup(app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT);
         app.forcingToImportant = null;
         updateProcessForegroundLocked(app, false, false);
         app.hasShownUi = false;
@@ -6585,7 +6474,7 @@
                         app.instr.mWatcher,
                         app.instr.mUiAutomationConnection, testMode,
                         mBinderTransactionTrackingEnabled, enableTrackAllocation,
-                        isRestrictedBackupMode || !normalMode, app.persistent,
+                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                         new Configuration(getGlobalConfiguration()), app.compat,
                         getCommonServicesLocked(app.isolated),
                         mCoreSettingsObserver.getCoreSettingsLocked(),
@@ -6594,7 +6483,7 @@
                 thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                         null, null, null, testMode,
                         mBinderTransactionTrackingEnabled, enableTrackAllocation,
-                        isRestrictedBackupMode || !normalMode, app.persistent,
+                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                         new Configuration(getGlobalConfiguration()), app.compat,
                         getCommonServicesLocked(app.isolated),
                         mCoreSettingsObserver.getCoreSettingsLocked(),
@@ -9457,7 +9346,7 @@
             if (conn.stableCount == 0 && conn.unstableCount == 0) {
                 cpr.connections.remove(conn);
                 conn.client.conProviders.remove(conn);
-                if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
+                if (conn.client.setProcState < PROCESS_STATE_LAST_ACTIVITY) {
                     // The client is more important than last activity -- note the time this
                     // is happening, so we keep the old provider process around a bit as last
                     // activity to avoid thrashing it.
@@ -10457,9 +10346,9 @@
                 && userId == UserHandle.USER_SYSTEM
                 && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
             // The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
-            r.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+            r.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
             r.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
-            r.persistent = true;
+            r.setPersistent(true);
             r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
         }
         if (isolated && isolatedUid != 0) {
@@ -10558,7 +10447,7 @@
         }
 
         if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
-            app.persistent = true;
+            app.setPersistent(true);
             app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
         }
         if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
@@ -11109,7 +10998,10 @@
 
 
     public static long getInputDispatchingTimeoutLocked(ActivityRecord r) {
-        return r != null ? getInputDispatchingTimeoutLocked(r.app) : KEY_DISPATCHING_TIMEOUT;
+        if (r == null || !r.hasProcess()) {
+            return KEY_DISPATCHING_TIMEOUT;
+        }
+        return getInputDispatchingTimeoutLocked((ProcessRecord) r.app.mOwner);
     }
 
     public static long getInputDispatchingTimeoutLocked(ProcessRecord r) {
@@ -11326,7 +11218,7 @@
                         Slog.d("UI_FIFO", "Set RenderThread tid " + tid + " for pid " + pid);
                     }
                     // promote to FIFO now
-                    if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
+                    if (proc.getCurrentSchedulingGroup() == ProcessList.SCHED_GROUP_TOP_APP) {
                         if (DEBUG_OOM_ADJ) Slog.d("UI_FIFO", "Promoting " + tid + "out of band");
                         if (mUseFifoUiScheduling) {
                             setThreadScheduler(proc.renderThreadTid,
@@ -12294,7 +12186,7 @@
 
         final boolean isFatal = Build.IS_ENG || Settings.Global
                 .getInt(mContext.getContentResolver(), Settings.Global.WTF_IS_FATAL, 0) != 0;
-        final boolean isSystem = (r == null) || r.persistent;
+        final boolean isSystem = (r == null) || r.isPersistent();
 
         if (isFatal && !isSystem) {
             mAppErrors.crashApplication(r, crashInfo);
@@ -12457,8 +12349,8 @@
         if (activity != null) {
             sb.append("Activity: ").append(activity.shortComponentName).append("\n");
         }
-        if (parent != null && parent.app != null && parent.app.pid != process.pid) {
-            sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
+        if (parent != null && parent.app != null && parent.app.getPid() != process.pid) {
+            sb.append("Parent-Process: ").append(parent.app.mName).append("\n");
         }
         if (parent != null && parent != activity) {
             sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
@@ -12560,25 +12452,27 @@
                 if (!allUsers && app.userId != userId) {
                     continue;
                 }
-                if ((app.thread != null) && (app.crashing || app.notResponding)) {
+                final boolean crashing = app.isCrashing();
+                final boolean notResponding = app.isNotResponding();
+                if ((app.thread != null) && (crashing || notResponding)) {
                     // This one's in trouble, so we'll generate a report for it
                     // crashes are higher priority (in case there's a crash *and* an anr)
                     ActivityManager.ProcessErrorStateInfo report = null;
-                    if (app.crashing) {
+                    if (crashing) {
                         report = app.crashingReport;
-                    } else if (app.notResponding) {
+                    } else if (notResponding) {
                         report = app.notRespondingReport;
                     }
 
                     if (report != null) {
                         if (errList == null) {
-                            errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
+                            errList = new ArrayList<>(1);
                         }
                         errList.add(report);
                     } else {
                         Slog.w(TAG, "Missing app error report, app = " + app.processName +
-                                " crashing = " + app.crashing +
-                                " notResponding = " + app.notResponding);
+                                " crashing = " + crashing +
+                                " notResponding = " + notResponding);
                     }
                 }
             }
@@ -12608,10 +12502,10 @@
         if (mHeavyWeightProcess == app) {
             outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
         }
-        if (app.persistent) {
+        if (app.isPersistent()) {
             outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
         }
-        if (app.activities.size() > 0) {
+        if (app.hasActivities()) {
             outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES;
         }
         outInfo.lastTrimLevel = app.trimMemoryLevel;
@@ -12645,7 +12539,7 @@
                         || (!allUids && app.uid != callingUid)) {
                     continue;
                 }
-                if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
+                if ((app.thread != null) && (!app.isCrashing() && !app.isNotResponding())) {
                     // Generate process state info for running application
                     ActivityManager.RunningAppProcessInfo currApp =
                         new ActivityManager.RunningAppProcessInfo(app.processName,
@@ -12658,7 +12552,7 @@
                                         app.adjSourceProcState);
                     } else if (app.adjSource instanceof ActivityRecord) {
                         ActivityRecord r = (ActivityRecord)app.adjSource;
-                        if (r.app != null) currApp.importanceReasonPid = r.app.pid;
+                        if (r.app != null) currApp.importanceReasonPid = r.app.getPid();
                     }
                     if (app.adjTarget instanceof ComponentName) {
                         currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
@@ -13461,11 +13355,11 @@
                         pw.println("  All known processes:");
                         needSep = true;
                     }
-                    pw.print(r.persistent ? "  *PERS*" : "  *APP*");
+                    pw.print(r.isPersistent() ? "  *PERS*" : "  *APP*");
                         pw.print(" UID "); pw.print(procs.keyAt(ia));
                         pw.print(" "); pw.println(r);
                     r.dump(pw, "    ");
-                    if (r.persistent) {
+                    if (r.isPersistent()) {
                         numPers++;
                     }
                 }
@@ -13617,27 +13511,27 @@
             needSep = false;
             mUserController.dump(pw, dumpAll);
         }
-        if (mHomeProcess != null && (dumpPackage == null
-                || mHomeProcess.pkgList.containsKey(dumpPackage))) {
+        if (mActivityTaskManager.mHomeProcess != null && (dumpPackage == null
+                || mActivityTaskManager.mHomeProcess.mPkgList.contains(dumpPackage))) {
             if (needSep) {
                 pw.println();
                 needSep = false;
             }
-            pw.println("  mHomeProcess: " + mHomeProcess);
+            pw.println("  mHomeProcess: " + mActivityTaskManager.mHomeProcess);
         }
-        if (mPreviousProcess != null && (dumpPackage == null
-                || mPreviousProcess.pkgList.containsKey(dumpPackage))) {
+        if (mActivityTaskManager.mPreviousProcess != null && (dumpPackage == null
+                || mActivityTaskManager.mPreviousProcess.mPkgList.contains(dumpPackage))) {
             if (needSep) {
                 pw.println();
                 needSep = false;
             }
-            pw.println("  mPreviousProcess: " + mPreviousProcess);
+            pw.println("  mPreviousProcess: " + mActivityTaskManager.mPreviousProcess);
         }
-        if (dumpAll && (mPreviousProcess == null || dumpPackage == null
-                || mPreviousProcess.pkgList.containsKey(dumpPackage))) {
+        if (dumpAll && (mActivityTaskManager.mPreviousProcess == null || dumpPackage == null
+                || mActivityTaskManager.mPreviousProcess.mPkgList.contains(dumpPackage))) {
             StringBuilder sb = new StringBuilder(128);
             sb.append("  mPreviousProcessVisibleTime: ");
-            TimeUtils.formatDuration(mPreviousProcessVisibleTime, sb);
+            TimeUtils.formatDuration(mActivityTaskManager.mPreviousProcessVisibleTime, sb);
             pw.println(sb);
         }
         if (mHeavyWeightProcess != null && (dumpPackage == null
@@ -13933,7 +13827,7 @@
                     continue;
                 }
                 r.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PROCS);
-                if (r.persistent) {
+                if (r.isPersistent()) {
                     numPers++;
                 }
             }
@@ -14043,15 +13937,15 @@
             proto.write(ActivityManagerServiceDumpProcessesProto.CONFIG_WILL_CHANGE, mActivityTaskManager.getFocusedStack().mConfigWillChange);
         }
 
-        if (mHomeProcess != null && (dumpPackage == null
-                || mHomeProcess.pkgList.containsKey(dumpPackage))) {
-            mHomeProcess.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.HOME_PROC);
+        if (mActivityTaskManager.mHomeProcess != null && (dumpPackage == null
+                || mActivityTaskManager.mHomeProcess.mPkgList.contains(dumpPackage))) {
+            ((ProcessRecord) mActivityTaskManager.mHomeProcess.mOwner).writeToProto(proto, ActivityManagerServiceDumpProcessesProto.HOME_PROC);
         }
 
-        if (mPreviousProcess != null && (dumpPackage == null
-                || mPreviousProcess.pkgList.containsKey(dumpPackage))) {
-            mPreviousProcess.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC);
-            proto.write(ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS, mPreviousProcessVisibleTime);
+        if (mActivityTaskManager.mPreviousProcess != null && (dumpPackage == null
+                || mActivityTaskManager.mPreviousProcess.mPkgList.contains(dumpPackage))) {
+            ((ProcessRecord) mActivityTaskManager.mPreviousProcess.mOwner).writeToProto(proto, ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC);
+            proto.write(ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS, mActivityTaskManager.mPreviousProcessVisibleTime);
         }
 
         if (mHeavyWeightProcess != null && (dumpPackage == null
@@ -14322,8 +14216,8 @@
         dumpProcessesToGc(pw, needSep, null);
 
         pw.println();
-        pw.println("  mHomeProcess: " + mHomeProcess);
-        pw.println("  mPreviousProcess: " + mPreviousProcess);
+        pw.println("  mHomeProcess: " + mActivityTaskManager.mHomeProcess);
+        pw.println("  mPreviousProcess: " + mActivityTaskManager.mPreviousProcess);
         if (mHeavyWeightProcess != null) {
             pw.println("  mHeavyWeightProcess: " + mHeavyWeightProcess);
         }
@@ -14495,20 +14389,20 @@
             pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
                     pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
                     pw.print(" pid=");
-                    if (r.app != null) pw.println(r.app.pid);
+                    if (r.hasProcess()) pw.println(r.app.getPid());
                     else pw.println("(not running)");
             if (dumpAll) {
                 r.dump(pw, innerPrefix);
             }
         }
-        if (r.app != null && r.app.thread != null) {
+        if (r.attachedToProcess()) {
             // flush anything that is already in the PrintWriter since the thread is going
             // to write to the file descriptor directly
             pw.flush();
             try {
                 TransferPipe tp = new TransferPipe();
                 try {
-                    r.app.thread.dumpActivity(tp.getWriteFd(),
+                    r.app.getThread().dumpActivity(tp.getWriteFd(),
                             r.appToken, innerPrefix, args);
                     tp.go(fd);
                 } finally {
@@ -14863,9 +14757,9 @@
                 continue;
             }
             pw.println(String.format("%s%s #%2d: %s",
-                    prefix, (r.persistent ? persistentLabel : normalLabel),
+                    prefix, (r.isPersistent() ? persistentLabel : normalLabel),
                     i, r.toString()));
-            if (r.persistent) {
+            if (r.isPersistent()) {
                 numPers++;
             }
         }
@@ -14918,7 +14812,7 @@
             ProcessRecord r = list.get(i).first;
             long token = proto.start(fieldId);
             String oomAdj = ProcessList.makeOomAdjString(r.setAdj);
-            proto.write(ProcessOomProto.PERSISTENT, r.persistent);
+            proto.write(ProcessOomProto.PERSISTENT, r.isPersistent());
             proto.write(ProcessOomProto.NUM, (origList.size()-1)-list.get(i).second);
             proto.write(ProcessOomProto.OOM_ADJ, oomAdj);
             int schedGroup = ProcessOomProto.SCHED_GROUP_UNKNOWN;
@@ -14941,7 +14835,7 @@
             }
             if (r.foregroundActivities) {
                 proto.write(ProcessOomProto.ACTIVITIES, true);
-            } else if (r.foregroundServices) {
+            } else if (r.hasForegroundServices()) {
                 proto.write(ProcessOomProto.SERVICES, true);
             }
             proto.write(ProcessOomProto.STATE, ProcessList.makeProcStateProtoEnum(r.curProcState));
@@ -15038,14 +14932,14 @@
             char foreground;
             if (r.foregroundActivities) {
                 foreground = 'A';
-            } else if (r.foregroundServices) {
+            } else if (r.hasForegroundServices()) {
                 foreground = 'S';
             } else {
                 foreground = ' ';
             }
             String procState = ProcessList.makeProcStateString(r.curProcState);
             pw.print(prefix);
-            pw.print(r.persistent ? persistentLabel : normalLabel);
+            pw.print(r.isPersistent() ? persistentLabel : normalLabel);
             pw.print(" #");
             int num = (origList.size()-1)-list.get(i).second;
             if (num < 10) pw.print(' ');
@@ -15660,7 +15554,7 @@
                 thread = r.thread;
                 pid = r.pid;
                 oomAdj = r.getSetAdjWithServices();
-                hasActivities = r.activities.size() > 0;
+                hasActivities = r.hasActivities();
             }
             if (thread != null) {
                 if (!opts.isCheckinRequest && opts.dumpDetails) {
@@ -15727,7 +15621,7 @@
                     if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
                         // Record this for posterity if the process has been stable.
                         r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
-                                reportType, endTime-startTime, r.pkgList);
+                                reportType, endTime-startTime, r.pkgList.mPkgList);
                     }
                 }
 
@@ -16163,7 +16057,7 @@
                 thread = r.thread;
                 pid = r.pid;
                 oomAdj = r.getSetAdjWithServices();
-                hasActivities = r.activities.size() > 0;
+                hasActivities = r.hasActivities();
             }
             if (thread == null) {
                 continue;
@@ -16225,7 +16119,7 @@
                 if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
                     // Record this for posterity if the process has been stable.
                     r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
-                            reportType, endTime-startTime, r.pkgList);
+                            reportType, endTime-startTime, r.pkgList.mPkgList);
                 }
             }
 
@@ -16791,7 +16685,7 @@
             ProcessRecord capp = conn.client;
             conn.dead = true;
             if (conn.stableCount > 0) {
-                if (!capp.persistent && capp.thread != null
+                if (!capp.isPersistent() && capp.thread != null
                         && capp.pid != 0
                         && capp.pid != MY_PID) {
                     capp.kill("depends on provider "
@@ -16853,8 +16747,8 @@
             app.waitDialog = null;
         }
 
-        app.crashing = false;
-        app.notResponding = false;
+        app.setCrashing(false);
+        app.setNotResponding(false);
 
         app.resetPackageList(mProcessStats);
         app.unlinkDeathRecipient();
@@ -16963,7 +16857,7 @@
             return false;
         }
 
-        if (!app.persistent || app.isolated) {
+        if (!app.isPersistent() || app.isolated) {
             if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
                     "Removing non-persistent process during cleanup: " + app);
             if (!replacingPid) {
@@ -16987,12 +16881,7 @@
                 TAG_CLEANUP, "Clean-up removing on hold: " + app);
         mProcessesOnHold.remove(app);
 
-        if (app == mHomeProcess) {
-            mHomeProcess = null;
-        }
-        if (app == mPreviousProcess) {
-            mPreviousProcess = null;
-        }
+        mAtmInternal.onCleanUpApplicationRecord(app.getWindowProcessController());
 
         if (restart && !app.isolated) {
             // We have components that still need to be running in the
@@ -18037,7 +17926,7 @@
                 isCallerSystem = true;
                 break;
             default:
-                isCallerSystem = (callerApp != null) && callerApp.persistent;
+                isCallerSystem = (callerApp != null) && callerApp.isPersistent();
                 break;
         }
 
@@ -19279,7 +19168,7 @@
 
         if (app.thread == null) {
             app.adjSeq = mAdjSeq;
-            app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+            app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND);
             app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
             app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ;
             app.completedAdjSeq = app.adjSeq;
@@ -19292,7 +19181,7 @@
         app.empty = false;
         app.cached = false;
 
-        final int activitiesSize = app.activities.size();
+        final WindowProcessController wpc = app.getWindowProcessController();
         final int appUid = app.info.uid;
         final int logUid = mCurOomAdjUid;
 
@@ -19308,7 +19197,7 @@
             app.adjSeq = mAdjSeq;
             app.curRawAdj = app.maxAdj;
             app.foregroundActivities = false;
-            app.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+            app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
             app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
             // System processes can do UI, and when they do we want to have
             // them trim their memory after the user leaves the UI.  To
@@ -19317,29 +19206,24 @@
             app.systemNoUi = true;
             if (app == TOP_APP) {
                 app.systemNoUi = false;
-                app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
+                app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
                 app.adjType = "pers-top-activity";
             } else if (app.hasTopUi) {
                 // sched group/proc state adjustment is below
                 app.systemNoUi = false;
                 app.adjType = "pers-top-ui";
-            } else if (activitiesSize > 0) {
-                for (int j = 0; j < activitiesSize; j++) {
-                    final ActivityRecord r = app.activities.get(j);
-                    if (r.visible) {
-                        app.systemNoUi = false;
-                    }
-                }
+            } else if (wpc.hasVisibleActivities()) {
+                app.systemNoUi = false;
             }
             if (!app.systemNoUi) {
               if (mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) {
                   // screen on, promote UI
                   app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
-                  app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
+                  app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
               } else {
                   // screen off, restrict UI scheduling
                   app.curProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
-                  app.curSchedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
+                  app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED);
               }
             }
             app.curAdj = app.maxAdj;
@@ -19438,120 +19322,127 @@
         }
 
         // Examine all activities if not already foreground.
-        if (!foregroundActivities && activitiesSize > 0) {
-            int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
-            for (int j = 0; j < activitiesSize; j++) {
-                final ActivityRecord r = app.activities.get(j);
-                if (r.app != app) {
-                    Log.e(TAG, "Found activity " + r + " in proc activity list using " + r.app
-                            + " instead of expected " + app);
-                    if (r.app == null || (r.app.uid == app.uid)) {
-                        // Only fix things up when they look sane
-                        r.setProcess(app);
-                    } else {
-                        continue;
-                    }
-                }
-                if (r.visible) {
-                    // App has a visible activity; only upgrade adjustment.
-                    if (adj > ProcessList.VISIBLE_APP_ADJ) {
-                        adj = ProcessList.VISIBLE_APP_ADJ;
-                        app.adjType = "vis-activity";
-                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                            reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                    "Raise adj to vis-activity: " + app);
+        if (!foregroundActivities && wpc.hasActivities()) {
+            final int[] adjHolder = new int[1];
+            adjHolder[0] = adj;
+            final boolean[] foregroundActivitiesHolder = new boolean[1];
+            foregroundActivitiesHolder[0] = foregroundActivities;
+            int[] procStateHolder = new int[1];
+            procStateHolder[0] = procState;
+            int[] schedGroupHolder = new int[1];
+            schedGroupHolder[0] = schedGroup;
+
+            int minLayer = wpc.computeOomAdjFromActivities(ProcessList.VISIBLE_APP_LAYER_MAX,
+                    new WindowProcessController.ComputeOomAdjCallback() {
+                        @Override
+                        public void onVisibleActivity() {
+                            // App has a visible activity; only upgrade adjustment.
+                            if (adjHolder[0] > ProcessList.VISIBLE_APP_ADJ) {
+                                adjHolder[0] = ProcessList.VISIBLE_APP_ADJ;
+                                app.adjType = "vis-activity";
+                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                                            "Raise adj to vis-activity: " + app);
+                                }
+                            }
+                            if (procStateHolder[0] > PROCESS_STATE_CUR_TOP) {
+                                procStateHolder[0] = PROCESS_STATE_CUR_TOP;
+                                app.adjType = "vis-activity";
+                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                                            "Raise procstate to vis-activity (top): " + app);
+                                }
+                            }
+                            if (schedGroupHolder[0] < ProcessList.SCHED_GROUP_DEFAULT) {
+                                schedGroupHolder[0] = ProcessList.SCHED_GROUP_DEFAULT;
+                            }
+                            app.cached = false;
+                            app.empty = false;
+                            foregroundActivitiesHolder[0] = true;
                         }
-                    }
-                    if (procState > PROCESS_STATE_CUR_TOP) {
-                        procState = PROCESS_STATE_CUR_TOP;
-                        app.adjType = "vis-activity";
-                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                            reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                    "Raise procstate to vis-activity (top): " + app);
+
+                        @Override
+                        public void onPausedActivity() {
+                            if (adjHolder[0] > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                                adjHolder[0] = ProcessList.PERCEPTIBLE_APP_ADJ;
+                                app.adjType = "pause-activity";
+                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                                            "Raise adj to pause-activity: "  + app);
+                                }
+                            }
+                            if (procStateHolder[0] > PROCESS_STATE_CUR_TOP) {
+                                procStateHolder[0] = PROCESS_STATE_CUR_TOP;
+                                app.adjType = "pause-activity";
+                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                                            "Raise procstate to pause-activity (top): "  + app);
+                                }
+                            }
+                            if (schedGroupHolder[0] < ProcessList.SCHED_GROUP_DEFAULT) {
+                                schedGroupHolder[0] = ProcessList.SCHED_GROUP_DEFAULT;
+                            }
+                            app.cached = false;
+                            app.empty = false;
+                            foregroundActivitiesHolder[0] = true;
                         }
-                    }
-                    if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
-                        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
-                    }
-                    app.cached = false;
-                    app.empty = false;
-                    foregroundActivities = true;
-                    final TaskRecord task = r.getTask();
-                    if (task != null && minLayer > 0) {
-                        final int layer = task.mLayerRank;
-                        if (layer >= 0 && minLayer > layer) {
-                            minLayer = layer;
+
+                        @Override
+                        public void onStoppingActivity(boolean finishing) {
+                            if (adjHolder[0] > ProcessList.PERCEPTIBLE_APP_ADJ) {
+                                adjHolder[0] = ProcessList.PERCEPTIBLE_APP_ADJ;
+                                app.adjType = "stop-activity";
+                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                                            "Raise adj to stop-activity: "  + app);
+                                }
+                            }
+                            // For the process state, we will at this point consider the process to
+                            // be cached. It will be cached either as an activity or empty depending
+                            // on whether the activity is finishing. We do this so that we can treat
+                            // the process as cached for purposes of memory trimming (determining
+                            // current memory level, trim command to send to process) since there
+                            // can be an arbitrary number of stopping processes and they should soon
+                            // all go into the cached state.
+                            if (!finishing) {
+                                if (procStateHolder[0] > PROCESS_STATE_LAST_ACTIVITY) {
+                                    procStateHolder[0] = PROCESS_STATE_LAST_ACTIVITY;
+                                    app.adjType = "stop-activity";
+                                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                                                "Raise procstate to stop-activity: " + app);
+                                    }
+                                }
+                            }
+                            app.cached = false;
+                            app.empty = false;
+                            foregroundActivitiesHolder[0] = true;
                         }
-                    }
-                    break;
-                } else if (r.isState(ActivityState.PAUSING, ActivityState.PAUSED)) {
-                    if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                        adj = ProcessList.PERCEPTIBLE_APP_ADJ;
-                        app.adjType = "pause-activity";
-                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                            reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                    "Raise adj to pause-activity: "  + app);
-                        }
-                    }
-                    if (procState > PROCESS_STATE_CUR_TOP) {
-                        procState = PROCESS_STATE_CUR_TOP;
-                        app.adjType = "pause-activity";
-                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                            reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                    "Raise procstate to pause-activity (top): "  + app);
-                        }
-                    }
-                    if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
-                        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
-                    }
-                    app.cached = false;
-                    app.empty = false;
-                    foregroundActivities = true;
-                } else if (r.isState(ActivityState.STOPPING)) {
-                    if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                        adj = ProcessList.PERCEPTIBLE_APP_ADJ;
-                        app.adjType = "stop-activity";
-                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                            reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                    "Raise adj to stop-activity: "  + app);
-                        }
-                    }
-                    // For the process state, we will at this point consider the
-                    // process to be cached.  It will be cached either as an activity
-                    // or empty depending on whether the activity is finishing.  We do
-                    // this so that we can treat the process as cached for purposes of
-                    // memory trimming (determing current memory level, trim command to
-                    // send to process) since there can be an arbitrary number of stopping
-                    // processes and they should soon all go into the cached state.
-                    if (!r.finishing) {
-                        if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
-                            procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
-                            app.adjType = "stop-activity";
-                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                                reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                        "Raise procstate to stop-activity: " + app);
+
+                        @Override
+                        public void onOtherActivity() {
+                            if (procStateHolder[0] > PROCESS_STATE_CACHED_ACTIVITY) {
+                                procStateHolder[0] = PROCESS_STATE_CACHED_ACTIVITY;
+                                app.adjType = "cch-act";
+                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
+                                            "Raise procstate to cached activity: " + app);
+                                }
                             }
                         }
-                    }
-                    app.cached = false;
-                    app.empty = false;
-                    foregroundActivities = true;
-                } else {
-                    if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
-                        procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
-                        app.adjType = "cch-act";
-                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
-                            reportOomAdjMessageLocked(TAG_OOM_ADJ,
-                                    "Raise procstate to cached activity: " + app);
-                        }
-                    }
-                }
-            }
+                    });
+
+            adj = adjHolder[0];
+            foregroundActivities = foregroundActivitiesHolder[0];
+            procState = procStateHolder[0];
+            schedGroup = schedGroupHolder[0];
+
             if (adj == ProcessList.VISIBLE_APP_ADJ) {
                 adj += minLayer;
             }
         }
-        if (procState > ActivityManager.PROCESS_STATE_CACHED_RECENT && app.recentTasks.size() > 0) {
+
+        if (procState > ActivityManager.PROCESS_STATE_CACHED_RECENT && app.hasRecentTasks()) {
             procState = ActivityManager.PROCESS_STATE_CACHED_RECENT;
             app.adjType = "cch-rec";
             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
@@ -19561,7 +19452,7 @@
 
         if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                 || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
-            if (app.foregroundServices) {
+            if (app.hasForegroundServices()) {
                 // The user is aware of this app, so make it visible.
                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                 procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
@@ -19622,7 +19513,7 @@
             }
         }
 
-        if (app == mHomeProcess) {
+        if (wpc == mActivityTaskManager.mHomeProcess) {
             if (adj > ProcessList.HOME_APP_ADJ) {
                 // This process is hosting what we currently consider to be the
                 // home app, so we don't want to let it go into the background.
@@ -19643,7 +19534,7 @@
             }
         }
 
-        if (app == mPreviousProcess && app.activities.size() > 0) {
+        if (wpc == mActivityTaskManager.mPreviousProcess && app.hasActivities()) {
             if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                 // This was the previous process that showed UI to the user.
                 // We want to try to keep it around more aggressively, to give
@@ -19656,8 +19547,8 @@
                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
                 }
             }
-            if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
-                procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+            if (procState > PROCESS_STATE_LAST_ACTIVITY) {
+                procState = PROCESS_STATE_LAST_ACTIVITY;
                 app.adjType = "previous";
                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                     reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
@@ -19720,7 +19611,7 @@
                                 "Raise procstate to started service: " + app);
                     }
                 }
-                if (app.hasShownUi && app != mHomeProcess) {
+                if (app.hasShownUi && wpc != mActivityTaskManager.mHomeProcess) {
                     // If this process has shown some UI, let it immediately
                     // go to the LRU list because it may be pretty heavy with
                     // UI stuff.  We'll tag it with a label just to help
@@ -19783,7 +19674,7 @@
                         }
                         int clientAdj = client.curRawAdj;
                         int clientProcState = client.curProcState;
-                        if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
+                        if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                             // If the other app is cached for any reason, for purposes here
                             // we are going to consider it empty.  The specific cached state
                             // doesn't propagate except under certain conditions.
@@ -19793,7 +19684,7 @@
                         if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                             // Not doing bind OOM management, so treat
                             // this guy more like a started service.
-                            if (app.hasShownUi && app != mHomeProcess) {
+                            if (app.hasShownUi && wpc != mActivityTaskManager.mHomeProcess) {
                                 // If this process has shown some UI, let it immediately
                                 // go to the LRU list because it may be pretty heavy with
                                 // UI stuff.  We'll tag it with a label just to help
@@ -19826,7 +19717,7 @@
                             // about letting this process get into the LRU
                             // list to be killed and restarted if needed for
                             // memory.
-                            if (app.hasShownUi && app != mHomeProcess
+                            if (app.hasShownUi && wpc != mActivityTaskManager.mHomeProcess
                                     && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                 if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
                                     adjType = "cch-bound-ui-services";
@@ -19870,9 +19761,10 @@
                             // This will treat important bound services identically to
                             // the top app, which may behave differently than generic
                             // foreground work.
-                            if (client.curSchedGroup > schedGroup) {
+                            final int curSchedGroup = client.getCurrentSchedulingGroup();
+                            if (curSchedGroup > schedGroup) {
                                 if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
-                                    schedGroup = client.curSchedGroup;
+                                    schedGroup = curSchedGroup;
                                 } else {
                                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                 }
@@ -20010,14 +19902,14 @@
                 }
                 int clientAdj = client.curRawAdj;
                 int clientProcState = client.curProcState;
-                if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
+                if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                     // If the other app is cached for any reason, for purposes here
                     // we are going to consider it empty.
                     clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                 }
                 String adjType = null;
                 if (adj > clientAdj) {
-                    if (app.hasShownUi && app != mHomeProcess
+                    if (app.hasShownUi && wpc != mActivityTaskManager.mHomeProcess
                             && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                         adjType = "cch-ui-provider";
                     } else {
@@ -20058,7 +19950,7 @@
                 if (procState > clientProcState) {
                     procState = clientProcState;
                 }
-                if (client.curSchedGroup > schedGroup) {
+                if (client.getCurrentSchedulingGroup() > schedGroup) {
                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                 }
                 if (adjType != null) {
@@ -20111,8 +20003,8 @@
                             "Raise adj to recent provider: " + app);
                 }
             }
-            if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
-                procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+            if (procState > PROCESS_STATE_LAST_ACTIVITY) {
+                procState = PROCESS_STATE_LAST_ACTIVITY;
                 app.adjType = "recent-provider";
                 if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                     reportOomAdjMessageLocked(TAG_OOM_ADJ,
@@ -20174,7 +20066,7 @@
             } else if (app.treatLikeActivity) {
                 // This is a cached process, but somebody wants us to treat it like it has
                 // an activity, okay!
-                procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
+                procState = PROCESS_STATE_CACHED_ACTIVITY;
                 app.adjType = "cch-as-act";
             }
         }
@@ -20233,7 +20125,7 @@
         // worry about this for max adj above, since max adj will always be used to
         // keep it out of the cached vaues.
         app.curAdj = app.modifyRawOomAdj(adj);
-        app.curSchedGroup = schedGroup;
+        app.setCurrentSchedulingGroup(schedGroup);
         app.curProcState = procState;
         app.foregroundActivities = foregroundActivities;
         app.completedAdjSeq = mAdjSeq;
@@ -20250,7 +20142,8 @@
         EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
                 swapPss * 1024, rss * 1024, statType, procState, pssDuration);
         proc.lastPssTime = now;
-        proc.baseProcessTracker.addPss(pss, uss, rss, true, statType, pssDuration, proc.pkgList);
+        proc.baseProcessTracker.addPss(
+                pss, uss, rss, true, statType, pssDuration, proc.pkgList.mPkgList);
         if (DEBUG_PSS) Slog.d(TAG_PSS,
                 "pss of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
                 + " state=" + ProcessList.makeProcStateString(procState));
@@ -20601,7 +20494,7 @@
                         }
                         app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince
                                 + " dur=" + checkDur + " limit=" + cpuLimit, true);
-                        app.baseProcessTracker.reportExcessiveCpu(app.pkgList);
+                        app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList);
                     }
                 }
                 app.lastCpuTime = app.curCpuTime;
@@ -20630,12 +20523,13 @@
             app.verifiedAdj = ProcessList.INVALID_ADJ;
         }
 
-        if (app.setSchedGroup != app.curSchedGroup) {
+        final int curSchedGroup = app.getCurrentSchedulingGroup();
+        if (app.setSchedGroup != curSchedGroup) {
             int oldSchedGroup = app.setSchedGroup;
-            app.setSchedGroup = app.curSchedGroup;
+            app.setSchedGroup = curSchedGroup;
             if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.uid) {
                 String msg = "Setting sched group of " + app.processName
-                        + " to " + app.curSchedGroup + ": " + app.adjType;
+                        + " to " + curSchedGroup + ": " + app.adjType;
                 reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
             }
             if (app.waitingToKill != null && app.curReceivers.isEmpty()
@@ -20644,7 +20538,7 @@
                 success = false;
             } else {
                 int processGroup;
-                switch (app.curSchedGroup) {
+                switch (curSchedGroup) {
                     case ProcessList.SCHED_GROUP_BACKGROUND:
                         processGroup = THREAD_GROUP_BG_NONINTERACTIVE;
                         break;
@@ -20662,10 +20556,11 @@
                 long oldId = Binder.clearCallingIdentity();
                 try {
                     setProcessGroup(app.pid, processGroup);
-                    if (app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
+                    if (curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
                         // do nothing if we already switched to RT
                         if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
-                            mActivityTaskManager.onTopProcChangedLocked(app);
+                            mActivityTaskManager.onTopProcChangedLocked(
+                                    app.getWindowProcessController());
                             if (mUseFifoUiScheduling) {
                                 // Switch UI pipeline for app to SCHED_FIFO
                                 app.savedPriority = Process.getThreadPriority(app.pid);
@@ -20696,8 +20591,9 @@
                             }
                         }
                     } else if (oldSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
-                               app.curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
-                        mActivityTaskManager.onTopProcChangedLocked(app);
+                            curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
+                        mActivityTaskManager.onTopProcChangedLocked(
+                                app.getWindowProcessController());
                         if (mUseFifoUiScheduling) {
                             try {
                                 // Reset UI pipeline to SCHED_OTHER
@@ -20726,7 +20622,7 @@
                 } catch (Exception e) {
                     if (false) {
                         Slog.w(TAG, "Failed setting process group of " + app.pid
-                                + " to " + app.curSchedGroup);
+                                + " to " + app.getCurrentSchedulingGroup());
                         Slog.w(TAG, "at location", e);
                     }
                 } finally {
@@ -20738,16 +20634,16 @@
             app.repForegroundActivities = app.foregroundActivities;
             changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
         }
-        if (app.repProcState != app.curProcState) {
-            app.repProcState = app.curProcState;
+        if (app.getReportedProcState() != app.curProcState) {
+            app.setReportedProcState(app.curProcState);
             if (app.thread != null) {
                 try {
                     if (false) {
                         //RuntimeException h = new RuntimeException("here");
-                        Slog.i(TAG, "Sending new process state " + app.repProcState
+                        Slog.i(TAG, "Sending new process state " + app.getReportedProcState()
                                 + " to " + app /*, h*/);
                     }
-                    app.thread.setProcessState(app.repProcState);
+                    app.thread.setProcessState(app.getReportedProcState());
                 } catch (RemoteException e) {
                 }
             }
@@ -21034,10 +20930,9 @@
     }
 
     private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
-        if (proc.thread != null) {
-            if (proc.baseProcessTracker != null) {
-                proc.baseProcessTracker.setState(proc.repProcState, memFactor, now, proc.pkgList);
-            }
+        if (proc.thread != null && proc.baseProcessTracker != null) {
+            proc.baseProcessTracker.setState(
+                    proc.getReportedProcState(), memFactor, now, proc.pkgList.mPkgList);
         }
     }
 
@@ -21055,8 +20950,8 @@
     @GuardedBy("this")
     final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
             boolean oomAdj) {
-        if (isForeground != proc.foregroundServices) {
-            proc.foregroundServices = isForeground;
+        if (isForeground != proc.hasForegroundServices()) {
+            proc.setHasForegroundServices(isForeground);
             ArrayList<ProcessRecord> curProcs = mForegroundPackages.get(proc.info.packageName,
                     proc.info.uid);
             if (isForeground) {
@@ -21126,7 +21021,8 @@
     @GuardedBy("this")
     final boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll) {
         final ActivityRecord TOP_ACT = resumedAppLocked();
-        final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
+        final ProcessRecord TOP_APP = TOP_ACT != null && TOP_ACT.hasProcess()
+                ? (ProcessRecord) TOP_ACT.app.mOwner : null;
         final boolean wasCached = app.cached;
 
         mAdjSeq++;
@@ -21151,7 +21047,8 @@
     @GuardedBy("this")
     final void updateOomAdjLocked() {
         final ActivityRecord TOP_ACT = resumedAppLocked();
-        final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
+        final ProcessRecord TOP_APP = TOP_ACT != null && TOP_ACT.hasProcess()
+                ? (ProcessRecord) TOP_ACT.app.mOwner : null;
         final long now = SystemClock.uptimeMillis();
         final long nowElapsed = SystemClock.elapsedRealtime();
         final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
@@ -21238,7 +21135,7 @@
                 // to the process, do that now.
                 if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
                     switch (app.curProcState) {
-                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
+                        case PROCESS_STATE_CACHED_ACTIVITY:
                         case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                         case ActivityManager.PROCESS_STATE_CACHED_RECENT:
                             // This process is a cached process holding activities...
@@ -21324,7 +21221,7 @@
 
                 // Count the number of process types.
                 switch (app.curProcState) {
-                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
+                    case PROCESS_STATE_CACHED_ACTIVITY:
                     case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                         mNumCachedHiddenProcs++;
                         numCached++;
@@ -21367,7 +21264,7 @@
                         if (uidRec.curProcState > app.curProcState) {
                             uidRec.curProcState = app.curProcState;
                         }
-                        if (app.foregroundServices) {
+                        if (app.hasForegroundServices()) {
                             uidRec.foregroundServices = true;
                         }
                     }
@@ -21442,8 +21339,8 @@
             }
             int factor = numTrimming/3;
             int minFactor = 2;
-            if (mHomeProcess != null) minFactor++;
-            if (mPreviousProcess != null) minFactor++;
+            if (mActivityTaskManager.mHomeProcess != null) minFactor++;
+            if (mActivityTaskManager.mPreviousProcess != null) minFactor++;
             if (factor < minFactor) factor = minFactor;
             int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
             for (int i=N-1; i>=0; i--) {
@@ -21461,19 +21358,6 @@
                             app.thread.scheduleTrimMemory(curLevel);
                         } catch (RemoteException e) {
                         }
-                        if (false) {
-                            // For now we won't do this; our memory trimming seems
-                            // to be good enough at this point that destroying
-                            // activities causes more harm than good.
-                            if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
-                                    && app != mHomeProcess && app != mPreviousProcess) {
-                                // Need to do this on its own message because the stack may not
-                                // be in a consistent state at this point.
-                                // For these apps we will also finish their activities
-                                // to help them free memory.
-                                mStackSupervisor.scheduleDestroyAllActivities(app, "trim");
-                            }
-                        }
                     }
                     app.trimMemoryLevel = curLevel;
                     step++;
@@ -22024,7 +21908,7 @@
         // has been removed.
         for (int i=mRemovedProcesses.size()-1; i>=0; i--) {
             final ProcessRecord app = mRemovedProcesses.get(i);
-            if (app.activities.size() == 0 && app.recentTasks.size() == 0
+            if (!app.hasActivitiesOrRecentTasks()
                     && app.curReceivers.isEmpty() && app.services.size() == 0) {
                 Slog.i(
                     TAG, "Exiting empty application process "
@@ -22043,7 +21927,7 @@
                 cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/);
                 mRemovedProcesses.remove(i);
 
-                if (app.persistent) {
+                if (app.isPersistent()) {
                     addAppLocked(app.info, null, false, null /* ABI override */);
                 }
             }
@@ -22069,7 +21953,7 @@
 
             for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
                 ProcessRecord r = mLruProcesses.get(i);
-                if (r.thread != null && r.persistent) {
+                if (r.thread != null && r.isPersistent()) {
                     sendSignal(r.pid, sig);
                 }
             }
@@ -22574,7 +22458,7 @@
                     final int NA = apps.size();
                     for (int ia = 0; ia < NA; ia++) {
                         final ProcessRecord app = apps.valueAt(ia);
-                        if (app.persistent) {
+                        if (app.isPersistent()) {
                             // We don't kill persistent processes.
                             continue;
                         }
@@ -22847,6 +22731,42 @@
         public void closeSystemDialogs(String reason) {
             ActivityManagerService.this.closeSystemDialogs(reason);
         }
+
+        public void killProcessesForRemovedTask(ArrayList<Object> procsToKill) {
+            synchronized (ActivityManagerService.this) {
+                for (int i = 0; i < procsToKill.size(); i++) {
+                    final WindowProcessController wpc =
+                            (WindowProcessController) procsToKill.get(i);
+                    final ProcessRecord pr = (ProcessRecord) wpc.mOwner;
+                    if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
+                            && pr.curReceivers.isEmpty()) {
+                        pr.kill("remove task", true);
+                    } else {
+                        // We delay killing processes that are not in the background or running a
+                        // receiver.
+                        pr.waitingToKill = "remove task";
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean hasRunningActivity(int uid, @Nullable String packageName) {
+            if (packageName == null) return false;
+
+            synchronized (ActivityManagerService.this) {
+                for (int i = 0; i < mLruProcesses.size(); i++) {
+                    final ProcessRecord pr = mLruProcesses.get(i);
+                    if (pr.uid != uid) {
+                        continue;
+                    }
+                    if (pr.getWindowProcessController().hasRunningActivity(packageName)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 1611a38..9b08823 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -2,7 +2,7 @@
 
 import static android.app.ActivityManager.START_SUCCESS;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
+import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -154,7 +154,7 @@
             launchedActivityLaunchToken = info.launchedActivity.info.launchToken;
             launchedActivityAppRecordRequiredAbi = info.launchedActivity.app == null
                     ? null
-                    : info.launchedActivity.app.requiredAbi;
+                    : info.launchedActivity.app.getRequiredAbi();
             reason = info.reason;
             startingWindowDelayMs = info.startingWindowDelayMs;
             bindApplicationDelayMs = info.bindApplicationDelayMs;
@@ -246,25 +246,11 @@
         // of caches might be purged so the time until it produces the first frame is very
         // interesting.
         final boolean processSwitch = processRecord == null
-                || !hasStartedActivity(processRecord, launchedActivity);
+                || !processRecord.getWindowProcessController().hasStartedActivity(launchedActivity);
 
         notifyActivityLaunched(resultCode, launchedActivity, processRunning, processSwitch);
     }
 
-    private boolean hasStartedActivity(ProcessRecord record, ActivityRecord launchedActivity) {
-        final ArrayList<ActivityRecord> activities = record.activities;
-        for (int i = activities.size() - 1; i >= 0; i--) {
-            final ActivityRecord activity = activities.get(i);
-            if (launchedActivity == activity) {
-                continue;
-            }
-            if (!activity.stopped) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     /**
      * Notifies the tracker the the activity is actually launching.
      *
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 7f3f8f3..d40b9b4 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -288,7 +288,7 @@
     AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
     HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
     UriPermissionOwner uriPermissions; // current special URI access perms.
-    ProcessRecord app;      // if non-null, hosting application
+    WindowProcessController app;      // if non-null, hosting application
     private ActivityState mState;    // current state we are in
     Bundle  icicle;         // last saved activity state
     PersistableBundle persistentState; // last persistently saved activity state
@@ -622,7 +622,7 @@
     }
 
     private void scheduleActivityMovedToDisplay(int displayId, Configuration config) {
-        if (app == null || app.thread == null) {
+        if (!attachedToProcess()) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.w(TAG,
                     "Can't report activity moved to display - client not running, activityRecord="
                             + this + ", displayId=" + displayId);
@@ -633,7 +633,7 @@
                     "Reporting activity moved to display" + ", activityRecord=" + this
                             + ", displayId=" + displayId + ", config=" + config);
 
-            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
                     MoveToDisplayItem.obtain(displayId, config));
         } catch (RemoteException e) {
             // If process died, whatever.
@@ -641,7 +641,7 @@
     }
 
     private void scheduleConfigurationChanged(Configuration config) {
-        if (app == null || app.thread == null) {
+        if (attachedToProcess()) {
             if (DEBUG_CONFIGURATION) Slog.w(TAG,
                     "Can't report activity configuration update - client not running"
                             + ", activityRecord=" + this);
@@ -651,7 +651,7 @@
             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
                     + config);
 
-            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
                     ActivityConfigurationChangeItem.obtain(config));
         } catch (RemoteException e) {
             // If process died, whatever.
@@ -659,7 +659,7 @@
     }
 
     void updateMultiWindowMode() {
-        if (task == null || task.getStack() == null || app == null || app.thread == null) {
+        if (task == null || task.getStack() == null || !attachedToProcess()) {
             return;
         }
 
@@ -678,7 +678,7 @@
 
     private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
         try {
-            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
                     MultiWindowModeChangeItem.obtain(mLastReportedMultiWindowMode, overrideConfig));
         } catch (Exception e) {
             // If process died, I don't care.
@@ -686,7 +686,7 @@
     }
 
     void updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate) {
-        if (task == null || task.getStack() == null || app == null || app.thread == null) {
+        if (task == null || task.getStack() == null || !attachedToProcess()) {
             return;
         }
 
@@ -705,7 +705,7 @@
 
     private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
         try {
-            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
                     PipModeChangeItem.obtain(mLastReportedPictureInPictureMode,
                             overrideConfig));
         } catch (Exception e) {
@@ -984,7 +984,7 @@
         }
     }
 
-    void setProcess(ProcessRecord proc) {
+    void setProcess(WindowProcessController proc) {
         app = proc;
         final ActivityRecord root = task != null ? task.getRootActivity() : null;
         if (root == this) {
@@ -992,6 +992,14 @@
         }
     }
 
+    boolean hasProcess() {
+        return app != null;
+    }
+
+    boolean attachedToProcess() {
+        return hasProcess() && app.hasThread();
+    }
+
     AppWindowContainerController getWindowContainerController() {
         return mWindowContainerController;
     }
@@ -1366,7 +1374,7 @@
             clearOptionsLocked();
         }
 
-        if (service.mAm != null) {
+        if (service != null) {
             service.getTaskChangeNotificationController().notifyTaskStackChanged();
         }
     }
@@ -1435,13 +1443,13 @@
         // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
         //   the user to see the visual effects caused by the intent delivery now.
         // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
-        if ((mState == RESUMED || mState == PAUSED
-                || isTopActivityWhileSleeping) && app != null && app.thread != null) {
+        if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
+                && attachedToProcess()) {
             try {
                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
                 ar.add(rintent);
                 service.getLifecycleManager().scheduleTransaction(
-                        app.thread, appToken, NewIntentItem.obtain(ar, mState == PAUSED));
+                        app.getThread(), appToken, NewIntentItem.obtain(ar, mState == PAUSED));
                 unsent = false;
             } catch (RemoteException e) {
                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
@@ -1744,7 +1752,7 @@
             }
             setVisible(true);
             sleeping = false;
-            app.pendingUiClean = true;
+            app.setPendingUiClean(true);
             if (reportToClient) {
                 makeClientVisible();
             } else {
@@ -1764,13 +1772,13 @@
     void makeClientVisible() {
         mClientVisibilityDeferred = false;
         try {
-            service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
+            service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
                     WindowVisibilityItem.obtain(true /* showWindow */));
             if (shouldPauseWhenBecomingVisible()) {
                 // An activity must be in the {@link PAUSING} state for the system to validate
                 // the move to {@link PAUSED}.
                 setState(PAUSING, "makeVisibleIfNeeded");
-                service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
+                service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
                         PauseActivityItem.obtain(finishing, false /* userLeaving */,
                                 configChangeFlags, false /* dontReport */));
             }
@@ -1816,7 +1824,7 @@
         stopFreezingScreenLocked(false);
         try {
             if (returningOptions != null) {
-                app.thread.scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
+                app.getThread().scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
             }
         } catch(RemoteException e) {
         }
@@ -1850,9 +1858,9 @@
         stopped = false;
 
         if (isActivityTypeHome()) {
-            ProcessRecord app = task.mActivities.get(0).app;
-            if (app != null && app != service.mAm.mHomeProcess) {
-                service.mAm.mHomeProcess = app;
+            WindowProcessController app = task.mActivities.get(0).app;
+            if (hasProcess() && app != service.mHomeProcess) {
+                service.mHomeProcess = app;
             }
         }
 
@@ -1873,8 +1881,8 @@
         // Mark the point when the activity is resuming
         // TODO: To be more accurate, the mark should be before the onCreate,
         //       not after the onResume. But for subsequent starts, onResume is fine.
-        if (app != null) {
-            cpuTimeAtResume = service.mAm.mProcessCpuTracker.getCpuTimeForPid(app.pid);
+        if (hasProcess()) {
+            cpuTimeAtResume = service.mAm.mProcessCpuTracker.getCpuTimeForPid(app.getPid());
         } else {
             cpuTimeAtResume = 0; // Couldn't get the cpu time of process
         }
@@ -1970,15 +1978,15 @@
 
     // IApplicationToken
 
-    public boolean mayFreezeScreenLocked(ProcessRecord app) {
+    public boolean mayFreezeScreenLocked(WindowProcessController app) {
         // Only freeze the screen if this activity is currently attached to
         // an application, and that application is not blocked or unresponding.
         // In any other case, we can't count on getting the screen unfrozen,
         // so it is best to leave as-is.
-        return app != null && !app.crashing && !app.notResponding;
+        return hasProcess() && !app.isCrashing() && !app.isNotResponding();
     }
 
-    public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
+    public void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
         if (mayFreezeScreenLocked(app)) {
             mWindowContainerController.startFreezingScreen(configChanges);
         }
@@ -2135,17 +2143,17 @@
     @Override
     public boolean keyDispatchingTimedOut(String reason, int windowPid) {
         ActivityRecord anrActivity;
-        ProcessRecord anrApp;
+        WindowProcessController anrApp;
         boolean windowFromSameProcessAsActivity;
         synchronized (service.mGlobalLock) {
             anrActivity = getWaitingHistoryRecordLocked();
             anrApp = app;
             windowFromSameProcessAsActivity =
-                    app == null || app.pid == windowPid || windowPid == -1;
+                    !hasProcess() || app.getPid() == windowPid || windowPid == -1;
         }
         if (windowFromSameProcessAsActivity) {
             return service.mAm.inputDispatchingTimedOut(
-                    anrApp, anrActivity, this, false, reason);
+                    (ProcessRecord) anrApp.mOwner, anrActivity, this, false, reason);
         } else {
             // In this case another process added windows using this activity token. So, we call the
             // generic service input dispatch timed out method so that the right process is blamed.
@@ -2202,9 +2210,9 @@
         if (!force && sleeping == _sleeping) {
             return;
         }
-        if (app != null && app.thread != null) {
+        if (attachedToProcess()) {
             try {
-                app.thread.scheduleSleeping(appToken, _sleeping);
+                app.getThread().scheduleSleeping(appToken, _sleeping);
                 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
                     mStackSupervisor.mGoingToSleepActivities.add(this);
                 }
@@ -2253,7 +2261,7 @@
     }
 
     final boolean isDestroyable() {
-        if (finishing || app == null) {
+        if (finishing || !hasProcess()) {
             // This would be redundant.
             return false;
         }
@@ -2593,7 +2601,7 @@
 
         // If the activity isn't currently running, just leave the new configuration and it will
         // pick that up next time it starts.
-        if (app == null || app.thread == null) {
+        if (!attachedToProcess()) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                     "Configuration doesn't matter not running " + this);
             stopFreezingScreenLocked(false);
@@ -2614,7 +2622,7 @@
             startFreezingScreenLocked(app, globalChanges);
             forceNewConfig = false;
             preserveWindow &= isResizeOnlyChange(changes);
-            if (app == null || app.thread == null) {
+            if (!attachedToProcess()) {
                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                         "Config is destroying non-running " + this);
                 stack.destroyActivityLocked(this, true, "config");
@@ -2774,7 +2782,7 @@
             } else {
                 lifecycleItem = PauseActivityItem.obtain();
             }
-            final ClientTransaction transaction = ClientTransaction.obtain(app.thread, appToken);
+            final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
             transaction.addCallback(callbackItem);
             transaction.setLifecycleStateRequest(lifecycleItem);
             service.getLifecycleManager().scheduleTransaction(transaction);
@@ -2804,11 +2812,11 @@
     }
 
     private boolean isProcessRunning() {
-        ProcessRecord proc = app;
+        WindowProcessController proc = app;
         if (proc == null) {
-            proc = service.mAm.mProcessNames.get(processName, info.applicationInfo.uid);
+            proc = service.mProcessNames.get(processName, info.applicationInfo.uid);
         }
-        return proc != null && proc.thread != null;
+        return proc != null && proc.hasThread();
     }
 
     /**
@@ -3037,8 +3045,8 @@
         proto.write(STATE, mState.toString());
         proto.write(VISIBLE, visible);
         proto.write(FRONT_OF_TASK, frontOfTask);
-        if (app != null) {
-            proto.write(PROC_ID, app.pid);
+        if (hasProcess()) {
+            proto.write(PROC_ID, app.getPid());
         }
         proto.write(TRANSLUCENT, !fullscreen);
         proto.end(token);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d177702..9b01919 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -367,9 +367,9 @@
     static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
 
     private static class ScheduleDestroyArgs {
-        final ProcessRecord mOwner;
+        final WindowProcessController mOwner;
         final String mReason;
-        ScheduleDestroyArgs(ProcessRecord owner, String reason) {
+        ScheduleDestroyArgs(WindowProcessController owner, String reason) {
             mOwner = owner;
             mReason = reason;
         }
@@ -392,8 +392,8 @@
                     // so we need to be conservative and assume it isn't.
                     Slog.w(TAG, "Activity pause timeout for " + r);
                     synchronized (mService.mGlobalLock) {
-                        if (r.app != null) {
-                            mService.mAm.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
+                        if (r.hasProcess()) {
+                            mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
                         }
                         activityPausedLocked(r.appToken, true);
                     }
@@ -402,7 +402,7 @@
                     ActivityRecord r = (ActivityRecord)msg.obj;
                     synchronized (mService.mGlobalLock) {
                         if (r.continueLaunchTickingLocked()) {
-                            mService.mAm.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
+                            mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
                         }
                     }
                 } break;
@@ -1453,15 +1453,15 @@
 
         mService.mAm.updateCpuStats();
 
-        if (prev.app != null && prev.app.thread != null) {
+        if (prev.attachedToProcess()) {
             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
             try {
                 EventLogTags.writeAmPauseActivity(prev.userId, System.identityHashCode(prev),
                         prev.shortComponentName, "userLeaving=" + userLeaving);
                 mService.mAm.updateUsageStats(prev, false);
 
-                mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
-                        PauseActivityItem.obtain(prev.finishing, userLeaving,
+                mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
+                        prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
                                 prev.configChangeFlags, pauseImmediately));
             } catch (Exception e) {
                 // Ignore exception, if process died other code will cleanup.
@@ -1563,7 +1563,7 @@
                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
                 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
                         "completedPausedLocked");
-            } else if (prev.app != null) {
+            } else if (prev.hasProcess()) {
                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
                         + " wasStopping=" + wasStopping + " visible=" + prev.visible);
                 if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) {
@@ -1620,9 +1620,9 @@
         if (prev != null) {
             prev.resumeKeyDispatchingLocked();
 
-            if (prev.app != null && prev.cpuTimeAtResume > 0
+            if (prev.hasProcess() && prev.cpuTimeAtResume > 0
                     && mService.mAm.mBatteryStatsService.isOnBattery()) {
-                long diff = mService.mAm.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
+                long diff = mService.mAm.mProcessCpuTracker.getCpuTimeForPid(prev.app.getPid())
                         - prev.cpuTimeAtResume;
                 if (diff > 0) {
                     BatteryStatsImpl bsi = mService.mAm.mBatteryStatsService.getActiveStatistics();
@@ -1904,7 +1904,7 @@
                                     true /* ignoreStopState */);
                         }
 
-                        if (r.app == null || r.app.thread == null) {
+                        if (!r.attachedToProcess()) {
                             if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
                                     resumeNextActivity, r)) {
                                 if (activityNdx >= activities.size()) {
@@ -2136,11 +2136,11 @@
             switch (r.getState()) {
                 case STOPPING:
                 case STOPPED:
-                    if (r.app != null && r.app.thread != null) {
+                    if (r.attachedToProcess()) {
                         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                                 "Scheduling invisibility: " + r);
-                        mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
-                                WindowVisibilityItem.obtain(false /* showWindow */));
+                        mService.getLifecycleManager().scheduleTransaction(r.app.getThread(),
+                                r.appToken, WindowVisibilityItem.obtain(false /* showWindow */));
                     }
 
                     // Reset the flag indicating that an app can enter picture-in-picture once the
@@ -2217,9 +2217,9 @@
 
             if (waitingActivity != null) {
                 mWindowManager.setWindowOpaque(waitingActivity.appToken, false);
-                if (waitingActivity.app != null && waitingActivity.app.thread != null) {
+                if (waitingActivity.attachedToProcess()) {
                     try {
-                        waitingActivity.app.thread.scheduleTranslucentConversionComplete(
+                        waitingActivity.app.getThread().scheduleTranslucentConversionComplete(
                                 waitingActivity.appToken, r != null);
                     } catch (RemoteException e) {
                     }
@@ -2451,8 +2451,9 @@
             // at the top of the LRU list, since we know we will be needing it
             // very soon and it would be a waste to let it get killed if it
             // happens to be sitting towards the end.
-            if (next.app != null && next.app.thread != null) {
-                mService.mAm.updateLruProcessLocked(next.app, true, null);
+            if (next.attachedToProcess()) {
+                next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
+                        true /* updateLru */, true /* activityChange */, false /* updateOomAdj */);
             }
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
             if (lastResumed != null) {
@@ -2577,7 +2578,7 @@
         mStackSupervisor.mNoAnimActivities.clear();
 
         ActivityStack lastStack = mStackSupervisor.getLastStack();
-        if (next.app != null && next.app.thread != null) {
+        if (next.attachedToProcess()) {
             if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                     + " stopped=" + next.stopped + " visible=" + next.visible);
 
@@ -2618,9 +2619,9 @@
 
                 next.setState(RESUMED, "resumeTopActivityInnerLocked");
 
-                mService.mAm.updateLruProcessLocked(next.app, true, null);
+                next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
+                        true /* updateLru */, true /* activityChange */, true /* updateOomAdj */);
                 updateLRUListLocked(next);
-                mService.mAm.updateOomAdjLocked();
 
                 // Have the window manager re-evaluate the orientation of
                 // the screen based on the new activity order.
@@ -2662,8 +2663,8 @@
                 }
 
                 try {
-                    final ClientTransaction transaction = ClientTransaction.obtain(next.app.thread,
-                            next.appToken);
+                    final ClientTransaction transaction =
+                            ClientTransaction.obtain(next.app.getThread(), next.appToken);
                     // Deliver all pending results.
                     ArrayList<ResultInfo> a = next.results;
                     if (a != null) {
@@ -2691,11 +2692,11 @@
                     next.sleeping = false;
                     mService.mAm.getAppWarningsLocked().onResumeActivity(next);
                     mService.mAm.showAskCompatModeDialogLocked(next);
-                    next.app.pendingUiClean = true;
-                    next.app.forceProcessStateUpTo(mService.mAm.mTopProcessState);
+                    next.app.setPendingUiCleanAndForceProcessStateUpTo(
+                            mService.mAm.mTopProcessState);
                     next.clearOptionsLocked();
                     transaction.setLifecycleStateRequest(
-                            ResumeActivityItem.obtain(next.app.repProcState,
+                            ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                     mService.isNextTransitionForward()));
                     mService.getLifecycleManager().scheduleTransaction(transaction);
 
@@ -3345,12 +3346,12 @@
         if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
                 + " : who=" + resultWho + " req=" + requestCode
                 + " res=" + resultCode + " data=" + data);
-        if (mResumedActivity == r && r.app != null && r.app.thread != null) {
+        if (mResumedActivity == r && r.attachedToProcess()) {
             try {
                 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
                 list.add(new ResultInfo(resultWho, requestCode,
                         resultCode, data));
-                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
+                mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken,
                         ActivityResultItem.obtain(list));
                 return;
             } catch (Exception e) {
@@ -3464,7 +3465,7 @@
             }
         }
 
-        if (r.app != null && r.app.thread != null) {
+        if (r.attachedToProcess()) {
             adjustFocusedActivityStack(r, "stopActivity");
             r.resumeKeyDispatchingLocked();
             try {
@@ -3479,7 +3480,7 @@
                 }
                 EventLogTags.writeAmStopActivity(
                         r.userId, System.identityHashCode(r), r.shortComponentName);
-                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
+                mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken,
                         StopActivityItem.obtain(r.visible, r.configChangeFlags));
                 if (shouldSleepOrShutDownActivities()) {
                     r.setSleeping(true);
@@ -3546,7 +3547,7 @@
      * @return The task that was finished in this stack, {@code null} if top running activity does
      *         not belong to the crashed app.
      */
-    final TaskRecord finishTopCrashedActivityLocked(ProcessRecord app, String reason) {
+    final TaskRecord finishTopCrashedActivityLocked(WindowProcessController app, String reason) {
         ActivityRecord r = topRunningActivityLocked();
         TaskRecord finishedTask = null;
         if (r == null || r.app != app) {
@@ -3578,7 +3579,7 @@
         if (activityNdx >= 0) {
             r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx);
             if (r.isState(RESUMED, PAUSING, PAUSED)) {
-                if (!r.isActivityTypeHome() || mService.mAm.mHomeProcess != r.app) {
+                if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) {
                     Slog.w(TAG, "  Force finishing activity "
                             + r.intent.getComponent().flattenToShortString());
                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
@@ -3606,13 +3607,12 @@
                 // Check if any of the activities are using voice
                 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
                     ActivityRecord r = tr.mActivities.get(activityNdx);
-                    if (r.voiceSession != null
-                            && r.voiceSession.asBinder() == sessionBinder) {
+                    if (r.voiceSession != null && r.voiceSession.asBinder() == sessionBinder) {
                         // Inform of cancellation
                         r.clearVoiceSessionLocked();
                         try {
-                            r.app.thread.scheduleLocalVoiceInteractionStarted((IBinder) r.appToken,
-                                    null);
+                            r.app.getThread().scheduleLocalVoiceInteractionStarted(
+                                    r.appToken, null);
                         } catch (RemoteException re) {
                             // Ok
                         }
@@ -4002,7 +4002,7 @@
                     // TODO(b/64750076): Check if calling pid should really be -1.
                     final int res = mService.getActivityStartController()
                             .obtainStarter(destIntent, "navigateUpTo")
-                            .setCaller(srec.app.thread)
+                            .setCaller(srec.app.getThread())
                             .setActivityInfo(aInfo)
                             .setResultTo(parent.appToken)
                             .setCallingPid(-1)
@@ -4169,13 +4169,13 @@
         }
     }
 
-    final void scheduleDestroyActivities(ProcessRecord owner, String reason) {
+    final void scheduleDestroyActivities(WindowProcessController owner, String reason) {
         Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
         msg.obj = new ScheduleDestroyArgs(owner, reason);
         mHandler.sendMessage(msg);
     }
 
-    private void destroyActivitiesLocked(ProcessRecord owner, String reason) {
+    private void destroyActivitiesLocked(WindowProcessController owner, String reason) {
         boolean lastIsOpaque = false;
         boolean activityRemoved = false;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -4220,7 +4220,7 @@
         return false;
     }
 
-    final int releaseSomeActivitiesLocked(ProcessRecord app, ArraySet<TaskRecord> tasks,
+    final int releaseSomeActivitiesLocked(WindowProcessController app, ArraySet<TaskRecord> tasks,
             String reason) {
         // Iterate over tasks starting at the back (oldest) first.
         if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + app);
@@ -4274,7 +4274,7 @@
     final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
         if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(TAG_SWITCH,
                 "Removing activity from " + reason + ": token=" + r
-                        + ", app=" + (r.app != null ? r.app.processName : "(null)"));
+                        + ", app=" + (r.hasProcess() ? r.app.mName : "(null)"));
 
         if (r.isState(DESTROYING, DESTROYED)) {
             if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already destroying."
@@ -4290,23 +4290,23 @@
 
         cleanUpActivityLocked(r, false, false);
 
-        final boolean hadApp = r.app != null;
+        final boolean hadApp = r.hasProcess();
 
         if (hadApp) {
             if (removeFromApp) {
-                r.app.activities.remove(r);
-                if (mService.mAm.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
+                r.app.removeActivity(r);
+                if (mService.mAm.mHeavyWeightProcess != null
+                        && mService.mAm.mHeavyWeightProcess.getWindowProcessController() == r.app
+                        && !r.app.hasActivities()) {
                     mService.mAm.mHeavyWeightProcess = null;
                     mService.mAm.mHandler.sendEmptyMessage(
                             ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
                 }
-                if (r.app.activities.isEmpty()) {
+                if (!r.app.hasActivities()) {
                     // Update any services we are bound to that might care about whether
                     // their client may have activities.
-                    mService.mAm.mServices.updateServiceConnectionActivitiesLocked(r.app);
                     // No longer have activities, so update LRU list and oom adj.
-                    mService.mAm.updateLruProcessLocked(r.app, false, null);
-                    mService.mAm.updateOomAdjLocked();
+                    r.app.updateProcessInfo(true, true, false, true);
                 }
             }
 
@@ -4314,7 +4314,7 @@
 
             try {
                 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
-                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
+                mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken,
                         DestroyActivityItem.obtain(r.finishing, r.configChangeFlags));
             } catch (Exception e) {
                 // We can just ignore exceptions here...  if the process
@@ -4405,7 +4405,7 @@
     }
 
     private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
-            ProcessRecord app, String listName) {
+            WindowProcessController app, String listName) {
         int i = list.size();
         if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
             "Removing app " + app + " from list " + listName + " with " + i + " entries");
@@ -4421,7 +4421,7 @@
         }
     }
 
-    private boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
+    private boolean removeHistoryRecordsForAppLocked(WindowProcessController app) {
         removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
         removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
                 "mStoppingActivities");
@@ -4895,7 +4895,7 @@
                         || (packageName == null && r.userId == userId);
                 if ((userId == UserHandle.USER_ALL || r.userId == userId)
                         && (sameComponent || r.getTask() == lastTask)
-                        && (r.app == null || evenPersistent || !r.app.persistent)) {
+                        && (r.app == null || evenPersistent || !r.app.isPersistent())) {
                     if (!doit) {
                         if (r.finishing) {
                             // If this activity is just finishing, then it is not
@@ -4915,8 +4915,8 @@
                     didSomething = true;
                     Slog.i(TAG, "  Force finishing activity " + r);
                     if (sameComponent) {
-                        if (r.app != null) {
-                            r.app.removed = true;
+                        if (r.hasProcess()) {
+                            r.app.setRemoved(true);
                         }
                         r.app = null;
                     }
@@ -4987,7 +4987,7 @@
      * @param app The app of the activity that died.
      * @return result from removeHistoryRecordsForAppLocked.
      */
-    boolean handleAppDiedLocked(ProcessRecord app) {
+    boolean handleAppDiedLocked(WindowProcessController app) {
         if (mPausingActivity != null && mPausingActivity.app == app) {
             if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
                     "App died while pausing: " + mPausingActivity);
@@ -5001,7 +5001,7 @@
         return removeHistoryRecordsForAppLocked(app);
     }
 
-    void handleAppCrashLocked(ProcessRecord app) {
+    void handleAppCrashLocked(WindowProcessController app) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 7503ec2..f49943e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -109,7 +109,9 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManager.StackInfo;
-import android.app.ActivityTaskManagerInternal.SleepToken;
+import android.app.ActivityManagerInternal;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
 import android.app.ActivityOptions;
 import android.app.AppOpsManager;
 import android.app.ProfilerInfo;
@@ -580,21 +582,21 @@
         final ActivityRecord sourceRecord;
         final int startFlags;
         final ActivityStack stack;
-        final ProcessRecord callerApp;
+        final WindowProcessController callerApp;
 
         PendingActivityLaunch(ActivityRecord _r, ActivityRecord _sourceRecord,
-                int _startFlags, ActivityStack _stack, ProcessRecord _callerApp) {
+                int _startFlags, ActivityStack _stack, WindowProcessController app) {
             r = _r;
             sourceRecord = _sourceRecord;
             startFlags = _startFlags;
             stack = _stack;
-            callerApp = _callerApp;
+            callerApp = app;
         }
 
         void sendErrorResult(String message) {
             try {
-                if (callerApp.thread != null) {
-                    callerApp.thread.scheduleCrash(message);
+                if (callerApp.hasThread()) {
+                    callerApp.getThread().scheduleCrash(message);
                 }
             } catch (RemoteException e) {
                 Slog.e(TAG, "Exception scheduling crash of failed "
@@ -1399,12 +1401,13 @@
         beginDeferResume();
 
         try {
-            r.startFreezingScreenLocked(app, 0);
+            final WindowProcessController proc = app.getWindowProcessController();
+            r.startFreezingScreenLocked(proc, 0);
 
             // schedule launch ticks to collect information about slow apps.
             r.startLaunchTickingLocked();
 
-            r.setProcess(app);
+            r.setProcess(proc);
 
             if (getKeyguardController().isKeyguardLocked()) {
                 r.notifyUnknownVisibilityLaunched();
@@ -1448,12 +1451,8 @@
 
             if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);
 
-            int idx = app.activities.indexOf(r);
-            if (idx < 0) {
-                app.activities.add(r);
-            }
-            mService.mAm.updateLruProcessLocked(app, true, null);
-            mService.mAm.updateOomAdjLocked();
+            proc.addActivityIfNeeded(r);
+            proc.updateProcessInfo(false, true, true, true);
 
             final LockTaskController lockTaskController = mService.getLockTaskController();
             if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
@@ -1483,7 +1482,7 @@
                         System.identityHashCode(r), task.taskId, r.shortComponentName);
                 if (r.isActivityTypeHome()) {
                     // Home process is the root process of the task.
-                    mService.mAm.mHomeProcess = task.mActivities.get(0).app;
+                    mService.mHomeProcess = task.mActivities.get(0).app;
                 }
                 mService.mAm.notifyPackageUse(r.intent.getComponent().getPackageName(),
                         PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
@@ -1534,9 +1533,9 @@
                         // and override configs.
                         mergedConfiguration.getGlobalConfiguration(),
                         mergedConfiguration.getOverrideConfiguration(), r.compat,
-                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
-                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
-                        profilerInfo));
+                        r.launchedFromPackage, task.voiceInteractor, app.getReportedProcState(),
+                        r.icicle, r.persistentState, results, newIntents,
+                        mService.isNextTransitionForward(), profilerInfo));
 
                 // Set desired final state.
                 final ActivityLifecycleItem lifecycleItem;
@@ -1587,7 +1586,7 @@
                 // This is the first time we failed -- restart process and
                 // retry.
                 r.launchFailed = true;
-                app.activities.remove(r);
+                proc.removeActivity(r);
                 throw e;
             }
         } finally {
@@ -1625,7 +1624,7 @@
         // Update any services we are bound to that might care about whether
         // their client may have activities.
         if (r.app != null) {
-            mService.mAm.mServices.updateServiceConnectionActivitiesLocked(r.app);
+            r.app.updateServiceConnectionActivities();
         }
 
         return true;
@@ -2129,7 +2128,7 @@
         return r;
     }
 
-    boolean handleAppDiedLocked(ProcessRecord app) {
+    boolean handleAppDiedLocked(WindowProcessController app) {
         boolean hasVisibleActivities = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
@@ -2192,7 +2191,7 @@
         // First, found out what is currently the foreground app, so that
         // we don't blow away the previous app if this activity is being
         // hosted by the process that is actually still the foreground.
-        ProcessRecord fgApp = null;
+        WindowProcessController fgApp = null;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
@@ -2211,11 +2210,11 @@
 
         // Now set this one as the previous process, only if that really
         // makes sense to.
-        if (r.app != null && fgApp != null && r.app != fgApp
-                && r.lastVisibleTime > mService.mAm.mPreviousProcessVisibleTime
-                && r.app != mService.mAm.mHomeProcess) {
-            mService.mAm.mPreviousProcess = r.app;
-            mService.mAm.mPreviousProcessVisibleTime = r.lastVisibleTime;
+        if (r.hasProcess() && fgApp != null && r.app != fgApp
+                && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
+                && r.app != mService.mHomeProcess) {
+            mService.mPreviousProcess = r.app;
+            mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
         }
     }
 
@@ -2261,7 +2260,7 @@
      * @param reason Reason to perform this action.
      * @return The task that was finished in this stack, {@code null} if haven't found any.
      */
-    TaskRecord finishTopCrashedActivitiesLocked(ProcessRecord app, String reason) {
+    TaskRecord finishTopCrashedActivitiesLocked(WindowProcessController app, String reason) {
         TaskRecord finishedTask = null;
         ActivityStack focusedStack = getFocusedStack();
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
@@ -3111,36 +3110,34 @@
 
         // Determine if the process(es) for this task should be killed.
         final String pkg = component.getPackageName();
-        ArrayList<ProcessRecord> procsToKill = new ArrayList<>();
-        ArrayMap<String, SparseArray<ProcessRecord>> pmap = mService.mAm.mProcessNames.getMap();
+        ArrayList<Object> procsToKill = new ArrayList<>();
+        ArrayMap<String, SparseArray<WindowProcessController>> pmap =
+                mService.mProcessNames.getMap();
         for (int i = 0; i < pmap.size(); i++) {
 
-            SparseArray<ProcessRecord> uids = pmap.valueAt(i);
+            SparseArray<WindowProcessController> uids = pmap.valueAt(i);
             for (int j = 0; j < uids.size(); j++) {
-                ProcessRecord proc = uids.valueAt(j);
-                if (proc.userId != tr.userId) {
+                WindowProcessController proc = uids.valueAt(j);
+                if (proc.mUserId != tr.userId) {
                     // Don't kill process for a different user.
                     continue;
                 }
-                if (proc == mService.mAm.mHomeProcess) {
+                if (proc == mService.mHomeProcess) {
                     // Don't kill the home process along with tasks from the same package.
                     continue;
                 }
-                if (!proc.pkgList.containsKey(pkg)) {
+                if (!proc.mPkgList.contains(pkg)) {
                     // Don't kill process that is not associated with this task.
                     continue;
                 }
 
-                for (int k = 0; k < proc.activities.size(); k++) {
-                    TaskRecord otherTask = proc.activities.get(k).getTask();
-                    if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
-                        // Don't kill process(es) that has an activity in a different task that is
-                        // also in recents.
-                        return;
-                    }
+                if (!proc.shouldKillProcessForRemovedTask(tr)) {
+                    // Don't kill process(es) that has an activity in a different task that is also
+                    // in recents.
+                    return;
                 }
 
-                if (proc.foregroundServices) {
+                if (proc.hasForegroundServices()) {
                     // Don't kill process(es) with foreground service.
                     return;
                 }
@@ -3150,17 +3147,12 @@
             }
         }
 
-        // Kill the running processes.
-        for (int i = 0; i < procsToKill.size(); i++) {
-            ProcessRecord pr = procsToKill.get(i);
-            if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
-                    && pr.curReceivers.isEmpty()) {
-                pr.kill("remove task", true);
-            } else {
-                // We delay killing processes that are not in the background or running a receiver.
-                pr.waitingToKill = "remove task";
-            }
-        }
+        // Kill the running processes. Post on handle since we don't want to hold the service lock
+        // while calling into AM.
+        final Runnable r = PooledLambda.obtainRunnable(
+                ActivityManagerInternal::killProcessesForRemovedTask, mService.mAmInternal,
+                procsToKill);
+        mService.mH.post(r);
     }
 
     /**
@@ -3663,7 +3655,7 @@
         return false;
     }
 
-    void handleAppCrashLocked(ProcessRecord app) {
+    void handleAppCrashLocked(WindowProcessController app) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
@@ -3765,7 +3757,7 @@
         }
     }
 
-    void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
+    void scheduleDestroyAllActivities(WindowProcessController app, String reason) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
@@ -3775,44 +3767,9 @@
         }
     }
 
-    void releaseSomeActivitiesLocked(ProcessRecord app, String reason) {
-        // Examine all activities currently running in the process.
-        TaskRecord firstTask = null;
+    void releaseSomeActivitiesLocked(WindowProcessController app, String reason) {
         // Tasks is non-null only if two or more tasks are found.
-        ArraySet<TaskRecord> tasks = null;
-        if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + app);
-        for (int i = 0; i < app.activities.size(); i++) {
-            ActivityRecord r = app.activities.get(i);
-            // First, if we find an activity that is in the process of being destroyed,
-            // then we just aren't going to do anything for now; we want things to settle
-            // down before we try to prune more activities.
-            if (r.finishing || r.isState(DESTROYING, DESTROYED)) {
-                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Abort release; already destroying: " + r);
-                return;
-            }
-            // Don't consider any activies that are currently not in a state where they
-            // can be destroyed.
-            if (r.visible || !r.stopped || !r.haveState
-                    || r.isState(RESUMED, PAUSING, PAUSED, STOPPING)) {
-                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
-                continue;
-            }
-
-            final TaskRecord task = r.getTask();
-            if (task != null) {
-                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + task
-                        + " from " + r);
-                if (firstTask == null) {
-                    firstTask = task;
-                } else if (firstTask != task) {
-                    if (tasks == null) {
-                        tasks = new ArraySet<>();
-                        tasks.add(firstTask);
-                    }
-                    tasks.add(task);
-                }
-            }
-        }
+        ArraySet<TaskRecord> tasks = app.getReleaseSomeActivitiesTasks();
         if (tasks == null) {
             if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Didn't find two or more tasks to release");
             return;
@@ -4205,16 +4162,16 @@
                     pw.print(innerPrefix); pw.println(r.app);
                 }
             }
-            if (client && r.app != null && r.app.thread != null) {
+            if (client && r.attachedToProcess()) {
                 // flush anything that is already in the PrintWriter since the thread is going
                 // to write to the file descriptor directly
                 pw.flush();
                 try {
                     TransferPipe tp = new TransferPipe();
                     try {
-                        r.app.thread.dumpActivity(tp.getWriteFd(), r.appToken, innerPrefix, args);
-                        // Short timeout, since blocking here can
-                        // deadlock with the application.
+                        r.app.getThread().dumpActivity(
+                                tp.getWriteFd(), r.appToken, innerPrefix, args);
+                        // Short timeout, since blocking here can deadlock with the application.
                         tp.go(fd, 2000);
                     } finally {
                         tp.kill();
@@ -4574,7 +4531,7 @@
 
         for (int i = task.mActivities.size() - 1; i >= 0; i--) {
             final ActivityRecord r = task.mActivities.get(i);
-            if (r.app != null && r.app.thread != null) {
+            if (r.attachedToProcess()) {
                 mMultiWindowModeChangedActivities.add(r);
             }
         }
@@ -4597,7 +4554,7 @@
     void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds) {
         for (int i = task.mActivities.size() - 1; i >= 0; i--) {
             final ActivityRecord r = task.mActivities.get(i);
-            if (r.app != null && r.app.thread != null) {
+            if (r.attachedToProcess()) {
                 mPipModeChangedActivities.add(r);
                 // If we are scheduling pip change, then remove this activity from multi-window
                 // change list as the processing of pip change will make sure multi-window changed
@@ -4616,7 +4573,7 @@
         mHandler.removeMessages(REPORT_PIP_MODE_CHANGED_MSG);
         for (int i = task.mActivities.size() - 1; i >= 0; i--) {
             final ActivityRecord r = task.mActivities.get(i);
-            if (r.app != null && r.app.thread != null) {
+            if (r.attachedToProcess()) {
                 r.updatePictureInPictureMode(targetStackBounds, forceUpdate);
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 6f58aea..dac7715 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -720,10 +720,11 @@
         abort |= !mService.mAm.mIntentFirewall.checkStartActivity(intent, callingUid,
                 callingPid, resolvedType, aInfo.applicationInfo);
 
+        final WindowProcessController callerWpc =
+                callerApp != null ? callerApp.getWindowProcessController() : null;
         // Merge the two options bundles, while realCallerOptions takes precedence.
         ActivityOptions checkedOptions = options != null
-                ? options.getOptions(intent, aInfo, callerApp, mSupervisor)
-                : null;
+                ? options.getOptions(intent, aInfo, callerWpc, mSupervisor) : null;
         if (allowPendingRemoteAnimationRegistryLookup) {
             checkedOptions = mService.getActivityStartController()
                     .getPendingRemoteAnimationRegistry()
@@ -847,7 +848,7 @@
             if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                     realCallingPid, realCallingUid, "Activity start")) {
                 mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
-                        sourceRecord, startFlags, stack, callerApp));
+                        sourceRecord, startFlags, stack, callerWpc));
                 ActivityOptions.abort(checkedOptions);
                 return ActivityManager.START_SWITCHES_CANCELED;
             }
@@ -1057,13 +1058,8 @@
                         }
                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
                                 new IntentSender(target));
-                        if (heavy.activities.size() > 0) {
-                            ActivityRecord hist = heavy.activities.get(0);
-                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
-                                    hist.packageName);
-                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
-                                    hist.getTask().taskId);
-                        }
+                        heavy.getWindowProcessController().updateIntentForHeavyWeightActivity(
+                                newIntent);
                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
                                 aInfo.packageName);
                         newIntent.setFlags(intent.getFlags());
@@ -1364,7 +1360,7 @@
         final boolean dontStart = top != null && mStartActivity.resultTo == null
                 && top.realActivity.equals(mStartActivity.realActivity)
                 && top.userId == mStartActivity.userId
-                && top.app != null && top.app.thread != null
+                && top.attachedToProcess()
                 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
         if (dontStart) {
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index d554e0f..d47fb44 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -26,10 +26,11 @@
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.Manifest.permission.STOP_APP_SWITCHES;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
+import static com.android.server.am.ActivityManagerService.dumpStackTraces;
+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 android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
 import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
@@ -46,7 +47,6 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
-import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
@@ -56,7 +56,6 @@
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
-import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
@@ -114,7 +113,7 @@
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
-import android.app.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
 import android.app.IActivityController;
 import android.app.IActivityTaskManager;
@@ -150,7 +149,9 @@
 import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
+import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.LocaleList;
@@ -159,6 +160,7 @@
 import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UpdateLock;
@@ -168,6 +170,7 @@
 import android.service.voice.VoiceInteractionManagerInternal;
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
+import android.text.format.Time;
 import android.util.ArrayMap;
 import android.util.EventLog;
 import android.util.Log;
@@ -176,6 +179,7 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.StatsLog;
+import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.view.IRecentsAnimationRunner;
 import android.view.RemoteAnimationAdapter;
@@ -184,6 +188,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.AssistUtils;
 import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.app.ProcessMap;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.logging.MetricsLoggerWrapper;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -199,10 +204,13 @@
 import com.android.server.wm.WindowManagerService;
 
 import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * System service for managing activities and their containers (task, stacks, displays,... ).
@@ -228,6 +236,18 @@
     Object mGlobalLock;
     ActivityStackSupervisor mStackSupervisor;
     WindowManagerService mWindowManager;
+    /** All processes currently running that might have a window organized by name. */
+    final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
+    /** This is the process holding what we currently consider to be the "home" activity. */
+    WindowProcessController mHomeProcess;
+    /**
+     * This is the process holding the activity the user last visited that is in a different process
+     * from the one they are currently in.
+     */
+    WindowProcessController mPreviousProcess;
+    /** The time at which the previous process was last visible. */
+    long mPreviousProcessVisibleTime;
+
     /** List of intents that were used to start the most recent tasks. */
     private RecentTasks mRecentTasks;
     /** State of external calls telling us if the device is awake or asleep. */
@@ -443,7 +463,6 @@
     // TODO: Will be converted to WM lock once transition is complete.
     void setActivityManagerService(ActivityManagerService am) {
         mAm = am;
-        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
         mGlobalLock = mAm;
         mH = new H(mAm.mHandlerThread.getLooper());
         mUiHandler = new UiHandler();
@@ -464,6 +483,10 @@
         mKeyguardController = mStackSupervisor.getKeyguardController();
     }
 
+    void onActivityManagerInternalAdded() {
+        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
+    }
+
     protected ActivityStackSupervisor createStackSupervisor() {
         final ActivityStackSupervisor supervisor = new ActivityStackSupervisor(this, mH.getLooper());
         supervisor.initialize();
@@ -621,7 +644,7 @@
                 SafeActivityOptions.abort(options);
                 return false;
             }
-            if (r.app == null || r.app.thread == null) {
+            if (!r.attachedToProcess()) {
                 // The caller is not running...  d'oh!
                 SafeActivityOptions.abort(options);
                 return false;
@@ -701,7 +724,7 @@
             // TODO(b/64750076): Check if calling pid should really be -1.
             final int res = getActivityStartController()
                     .obtainStarter(intent, "startNextMatchingActivity")
-                    .setCaller(r.app.thread)
+                    .setCaller(r.app.getThread())
                     .setResolvedType(r.resolvedType)
                     .setActivityInfo(aInfo)
                     .setResultTo(resultTo != null ? resultTo.appToken : null)
@@ -804,12 +827,12 @@
             if (sourceRecord.app == null) {
                 throw new SecurityException("Called without a process attached to activity");
             }
-            if (UserHandle.getAppId(sourceRecord.app.uid) != SYSTEM_UID) {
+            if (UserHandle.getAppId(sourceRecord.app.mUid) != SYSTEM_UID) {
                 // This is still okay, as long as this activity is running under the
                 // uid of the original calling activity.
-                if (sourceRecord.app.uid != sourceRecord.launchedFromUid) {
+                if (sourceRecord.app.mUid != sourceRecord.launchedFromUid) {
                     throw new SecurityException(
-                            "Calling activity in uid " + sourceRecord.app.uid
+                            "Calling activity in uid " + sourceRecord.app.mUid
                                     + " must be system uid or original calling uid "
                                     + sourceRecord.launchedFromUid);
                 }
@@ -830,7 +853,7 @@
         }
 
         if (userId == UserHandle.USER_NULL) {
-            userId = UserHandle.getUserId(sourceRecord.app.uid);
+            userId = UserHandle.getUserId(sourceRecord.app.mUid);
         }
 
         // TODO: Switch to user app stacks here.
@@ -1062,20 +1085,25 @@
     @Override
     public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
         final long origId = Binder.clearCallingIdentity();
-        synchronized (mGlobalLock) {
-            ActivityStack stack = ActivityRecord.getStackLocked(token);
-            if (stack != null) {
-                ActivityRecord r =
-                        mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
-                                false /* processPausingActivities */, config);
-                if (stopProfiling) {
-                    if ((mAm.mProfileProc == r.app) && mAm.mProfilerInfo != null) {
-                        mAm.clearProfilerLocked();
-                    }
+        try {
+            WindowProcessController proc = null;
+            synchronized (mGlobalLock) {
+                ActivityStack stack = ActivityRecord.getStackLocked(token);
+                if (stack == null) {
+                    return;
+                }
+                final ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token,
+                        false /* fromTimeout */, false /* processPausingActivities */, config);
+                if (r != null) {
+                    proc = r.app;
+                }
+                if (stopProfiling && proc != null) {
+                    proc.clearProfilerIfNeeded();
                 }
             }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
         }
-        Binder.restoreCallingIdentity(origId);
     }
 
     @Override
@@ -2237,9 +2265,9 @@
         mH.post(() -> {
             synchronized (mGlobalLock) {
                 ActivityRecord r = ActivityRecord.forTokenLocked(token);
-                if (r != null && r.app != null && r.app.thread != null) {
+                if (r != null && r.attachedToProcess()) {
                     try {
-                        r.app.thread.scheduleEnterAnimationComplete(r.appToken);
+                        r.app.getThread().scheduleEnterAnimationComplete(r.appToken);
                     } catch (RemoteException e) {
                     }
                 }
@@ -2477,7 +2505,8 @@
         synchronized (mGlobalLock) {
             final long origId = Binder.clearCallingIdentity();
             try {
-                ProcessRecord app = mAm.getRecordForAppLocked(appInt);
+                WindowProcessController app =
+                        mAm.getRecordForAppLocked(appInt).getWindowProcessController();
                 mStackSupervisor.releaseSomeActivitiesLocked(app, "low-mem");
             } finally {
                 Binder.restoreCallingIdentity(origId);
@@ -2777,7 +2806,7 @@
                 Slog.w(TAG, "getAssistContextExtras failed: no top activity");
                 return null;
             }
-            if (activity.app == null || activity.app.thread == null) {
+            if (!activity.attachedToProcess()) {
                 Slog.w(TAG, "getAssistContextExtras failed: no process for " + activity);
                 return null;
             }
@@ -2797,7 +2826,7 @@
                             + " couldn't be found");
                     return null;
                 }
-                if (activity.app == null || activity.app.thread == null) {
+                if (!activity.attachedToProcess()) {
                     Slog.w(TAG, "enqueueAssistContext failed: no process for " + activity);
                     return null;
                 }
@@ -2809,7 +2838,7 @@
                 extras.putAll(args);
             }
             extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
-            extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.uid);
+            extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.mUid);
 
             pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras,
                     userHandle);
@@ -2820,8 +2849,8 @@
                 mViSessionId++;
             }
             try {
-                activity.app.thread.requestAssistContextExtras(activity.appToken, pae, requestType,
-                        mViSessionId, flags);
+                activity.app.getThread().requestAssistContextExtras(activity.appToken, pae,
+                        requestType, mViSessionId, flags);
                 mPendingAssistExtras.add(pae);
                 mUiHandler.postDelayed(pae, timeout);
             } catch (RemoteException e) {
@@ -3800,7 +3829,7 @@
             synchronized (mAm.mPidsSelfLocked) {
                 final int pid = Binder.getCallingPid();
                 final ProcessRecord proc = mAm.mPidsSelfLocked.get(pid);
-                mVrController.setVrThreadLocked(tid, pid, proc);
+                mVrController.setVrThreadLocked(tid, pid, proc.getWindowProcessController());
             }
         }
     }
@@ -3905,7 +3934,7 @@
         mRecentTasks.notifyTaskPersisterLocked(task, flush);
     }
 
-    void onTopProcChangedLocked(ProcessRecord proc) {
+    void onTopProcChangedLocked(WindowProcessController proc) {
         mVrController.onTopProcChangedLocked(proc);
     }
 
@@ -4307,6 +4336,65 @@
         return kept;
     }
 
+    void logAppTooSlow(WindowProcessController app, long startTime, String msg) {
+        if (true || Build.IS_USER) {
+            return;
+        }
+
+        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+        StrictMode.allowThreadDiskWrites();
+        try {
+            File tracesDir = new File("/data/anr");
+            File tracesFile = null;
+            try {
+                tracesFile = File.createTempFile("app_slow", null, tracesDir);
+
+                StringBuilder sb = new StringBuilder();
+                Time tobj = new Time();
+                tobj.set(System.currentTimeMillis());
+                sb.append(tobj.format("%Y-%m-%d %H:%M:%S"));
+                sb.append(": ");
+                TimeUtils.formatDuration(SystemClock.uptimeMillis()-startTime, sb);
+                sb.append(" since ");
+                sb.append(msg);
+                FileOutputStream fos = new FileOutputStream(tracesFile);
+                fos.write(sb.toString().getBytes());
+                if (app == null) {
+                    fos.write("\n*** No application process!".getBytes());
+                }
+                fos.close();
+                FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
+            } catch (IOException e) {
+                Slog.w(TAG, "Unable to prepare slow app traces file: " + tracesFile, e);
+                return;
+            }
+
+            if (app != null && app.getPid() > 0) {
+                ArrayList<Integer> firstPids = new ArrayList<Integer>();
+                firstPids.add(app.getPid());
+                dumpStackTraces(tracesFile.getAbsolutePath(), firstPids, null, null);
+            }
+
+            File lastTracesFile = null;
+            File curTracesFile = null;
+            for (int i=9; i>=0; i--) {
+                String name = String.format(Locale.US, "slow%02d.txt", i);
+                curTracesFile = new File(tracesDir, name);
+                if (curTracesFile.exists()) {
+                    if (lastTracesFile != null) {
+                        curTracesFile.renameTo(lastTracesFile);
+                    } else {
+                        curTracesFile.delete();
+                    }
+                }
+                lastTracesFile = curTracesFile;
+            }
+            tracesFile.renameTo(curTracesFile);
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+    }
+
     final class H extends Handler {
         public H(Looper looper) {
             super(looper, null, true);
@@ -4487,26 +4575,6 @@
         }
 
         @Override
-        public boolean hasRunningActivity(int uid, @Nullable String packageName) {
-            if (packageName == null) return false;
-
-            synchronized (mGlobalLock) {
-                for (int i = 0; i < mAm.mLruProcesses.size(); i++) {
-                    final ProcessRecord processRecord = mAm.mLruProcesses.get(i);
-                    if (processRecord.uid == uid) {
-                        for (int j = 0; j < processRecord.activities.size(); j++) {
-                            final ActivityRecord activityRecord = processRecord.activities.get(j);
-                            if (packageName.equals(activityRecord.packageName)) {
-                                return true;
-                            }
-                        }
-                    }
-                }
-            }
-            return false;
-        }
-
-        @Override
         public void registerScreenObserver(ScreenObserver observer) {
             mScreenObservers.add(observer);
         }
@@ -4575,5 +4643,31 @@
                         caller, callingPid, callingUid);
             }
         }
+
+        @Override
+        public void onProcessAdded(WindowProcessController proc) {
+            synchronized (mGlobalLock) {
+                mProcessNames.put(proc.mName, proc.mUid, proc);
+            }
+        }
+
+        @Override
+        public void onProcessRemoved(String name, int uid) {
+            synchronized (mGlobalLock) {
+                mProcessNames.remove(name, uid);
+            }
+        }
+
+        @Override
+        public void onCleanUpApplicationRecord(WindowProcessController proc) {
+            synchronized (mGlobalLock) {
+                if (proc == mHomeProcess) {
+                    mHomeProcess = null;
+                }
+                if (proc == mPreviousProcess) {
+                    mPreviousProcess = null;
+                }
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 68c63a2..cde633d 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -92,7 +92,7 @@
         attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR
                 | WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
         getWindow().setAttributes(attrs);
-        if (mProc.persistent) {
+        if (mProc.isPersistent()) {
             getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
         }
 
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 5719490..7db98b3 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -25,7 +25,6 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
-import android.app.ActivityThread;
 import android.app.AppOpsManager;
 import android.app.ApplicationErrorReport;
 import android.app.Dialog;
@@ -45,7 +44,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.EventLog;
-import android.util.Log;
 import android.util.Slog;
 import android.util.StatsLog;
 import android.util.SparseArray;
@@ -57,7 +55,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Set;
 
 import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
@@ -314,9 +311,9 @@
     }
 
     void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) {
-        app.crashing = false;
+        app.setCrashing(false);
         app.crashingReport = null;
-        app.notResponding = false;
+        app.setNotResponding(false);
         app.notRespondingReport = null;
         if (app.anrDialog == fromDialog) {
             app.anrDialog = null;
@@ -409,7 +406,7 @@
 
         // If a persistent app is stuck in a crash loop, the device isn't very
         // usable, so we want to consider sending out a rescue party.
-        if (r != null && r.persistent) {
+        if (r != null && r.isPersistent()) {
             RescueParty.notePersistentAppCrash(mContext, r.uid);
         }
 
@@ -493,8 +490,8 @@
                 long orig = Binder.clearCallingIdentity();
                 try {
                     // Kill it with fire!
-                    mService.mStackSupervisor.handleAppCrashLocked(r);
-                    if (!r.persistent) {
+                    mService.mStackSupervisor.handleAppCrashLocked(r.getWindowProcessController());
+                    if (!r.isPersistent()) {
                         mService.removeProcessLocked(r, false, false, "crash");
                         mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
                     }
@@ -571,11 +568,11 @@
 
     private boolean makeAppCrashingLocked(ProcessRecord app,
             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
-        app.crashing = true;
+        app.setCrashing(true);
         app.crashingReport = generateProcessError(app,
                 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
         startAppProblemLocked(app);
-        app.stopFreezingAllLocked();
+        app.getWindowProcessController().stopFreezingActivities();
         return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
                 data);
     }
@@ -643,7 +640,7 @@
             return null;
         }
 
-        if (!r.crashing && !r.notResponding && !r.forceCrashReport) {
+        if (!r.isCrashing() && !r.isNotResponding() && !r.forceCrashReport) {
             return null;
         }
 
@@ -654,10 +651,10 @@
         report.time = timeMillis;
         report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
 
-        if (r.crashing || r.forceCrashReport) {
+        if (r.isCrashing() || r.forceCrashReport) {
             report.type = ApplicationErrorReport.TYPE_CRASH;
             report.crashInfo = crashInfo;
-        } else if (r.notResponding) {
+        } else if (r.isNotResponding()) {
             report.type = ApplicationErrorReport.TYPE_ANR;
             report.anrInfo = new ApplicationErrorReport.AnrInfo();
 
@@ -715,8 +712,8 @@
                     + " has crashed too many times: killing!");
             EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
                     app.userId, app.info.processName, app.uid);
-            mService.mStackSupervisor.handleAppCrashLocked(app);
-            if (!app.persistent) {
+            mService.mStackSupervisor.handleAppCrashLocked(app.getWindowProcessController());
+            if (!app.isPersistent()) {
                 // We don't want to start this process again until the user
                 // explicitly does so...  but for persistent process, we really
                 // need to keep it running.  If a persistent process is actually
@@ -744,7 +741,7 @@
             mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
         } else {
             final TaskRecord affectedTask =
-                    mService.mStackSupervisor.finishTopCrashedActivitiesLocked(app, reason);
+                    mService.mStackSupervisor.finishTopCrashedActivitiesLocked(app.getWindowProcessController(), reason);
             if (data != null) {
                 data.task = affectedTask;
             }
@@ -762,21 +759,11 @@
         // replaced by a third-party app, clear the package preferred activities from packages
         // with a home activity running in the process to prevent a repeatedly crashing app
         // from blocking the user to manually clear the list.
-        final ArrayList<ActivityRecord> activities = app.activities;
-        if (app == mService.mHomeProcess && activities.size() > 0
-                && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
-                if (r.isActivityTypeHome()) {
-                    Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
-                    try {
-                        ActivityThread.getPackageManager()
-                                .clearPackagePreferredActivities(r.packageName);
-                    } catch (RemoteException c) {
-                        // pm is in same process, this will never happen.
-                    }
-                }
-            }
+        final WindowProcessController proc = app.getWindowProcessController();
+        final WindowProcessController homeProc = mService.mActivityTaskManager.mHomeProcess;
+        if (proc == homeProc && proc.hasActivities()
+                && (homeProc.mInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+            proc.clearPackagePreferredForHomeActivities();
         }
 
         if (!app.isolated) {
@@ -917,10 +904,10 @@
             if (mService.mShuttingDown) {
                 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
                 return;
-            } else if (app.notResponding) {
+            } else if (app.isNotResponding()) {
                 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
                 return;
-            } else if (app.crashing) {
+            } else if (app.isCrashing()) {
                 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
                 return;
             } else if (app.killedByAm) {
@@ -933,7 +920,7 @@
 
             // In case we come through here for the same app before completing
             // this one, mark as anring now so we will bail out.
-            app.notResponding = true;
+            app.setNotResponding(true);
 
             // Log the ANR to the event log.
             EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
@@ -946,8 +933,8 @@
             isSilentANR = !showBackground && !isInterestingForBackgroundTraces(app);
             if (!isSilentANR) {
                 int parentPid = app.pid;
-                if (parent != null && parent.app != null && parent.app.pid > 0) {
-                    parentPid = parent.app.pid;
+                if (parent != null && parent.app != null && parent.app.getPid() > 0) {
+                    parentPid = parent.app.getPid();
                 }
                 if (parentPid != app.pid) firstPids.add(parentPid);
 
@@ -958,7 +945,7 @@
                     if (r != null && r.thread != null) {
                         int pid = r.pid;
                         if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
-                            if (r.persistent) {
+                            if (r.isPersistent()) {
                                 firstPids.add(pid);
                                 if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
                             } else if (r.treatLikeActivity) {
@@ -1100,12 +1087,12 @@
 
     private void makeAppNotRespondingLocked(ProcessRecord app,
             String activity, String shortMsg, String longMsg) {
-        app.notResponding = true;
+        app.setNotResponding(true);
         app.notRespondingReport = generateProcessError(app,
                 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
                 activity, shortMsg, longMsg, null);
         startAppProblemLocked(app);
-        app.stopFreezingAllLocked();
+        app.getWindowProcessController().stopFreezingActivities();
     }
 
     void handleShowAnrUi(Message msg) {
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 8a88a69..7c983ff 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -157,7 +157,7 @@
                                     System.currentTimeMillis(), null);
                         }
 
-                        app.notResponding = false;
+                        app.setNotResponding(false);
                         app.notRespondingReport = null;
                         if (app.anrDialog == AppNotRespondingDialog.this) {
                             app.anrDialog = null;
diff --git a/services/core/java/com/android/server/am/AssistDataRequester.java b/services/core/java/com/android/server/am/AssistDataRequester.java
index 037f245..395b0da 100644
--- a/services/core/java/com/android/server/am/AssistDataRequester.java
+++ b/services/core/java/com/android/server/am/AssistDataRequester.java
@@ -17,13 +17,12 @@
 package com.android.server.am;
 
 import static android.app.ActivityManager.ASSIST_CONTEXT_FULL;
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_NONE;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
 
 import android.app.ActivityTaskManager;
 import android.app.AppOpsManager;
-import android.app.IActivityManager;
 import android.app.IAssistDataReceiver;
 import android.content.Context;
 import android.graphics.Bitmap;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index c9a26cb..a9fd51d 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -304,7 +304,7 @@
             app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                     mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
                     r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
-                    app.repProcState);
+                    app.getReportedProcState());
             if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                     "Process cur broadcast " + r + " DELIVERED for app " + app);
             started = true;
@@ -492,7 +492,7 @@
                 // correctly ordered with other one-way calls.
                 try {
                     app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
-                            data, extras, ordered, sticky, sendingUser, app.repProcState);
+                            data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
                 // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
                 // DeadObjectException when the process isn't actually dead.
                 //} catch (DeadObjectException ex) {
@@ -618,7 +618,7 @@
         }
 
         if (!skip && (filter.receiverList.app == null || filter.receiverList.app.killed
-                || filter.receiverList.app.crashing)) {
+                || filter.receiverList.app.isCrashing())) {
             Slog.w(TAG, "Skipping deliver [" + mQueueName + "] " + r
                     + " to " + filter.receiverList + ": process gone or crashing");
             skip = true;
@@ -885,7 +885,7 @@
                 synchronized (mService.mPidsSelfLocked) {
                     ProcessRecord proc = mService.mPidsSelfLocked.get(
                             mPendingBroadcast.curApp.pid);
-                    isDead = proc == null || proc.crashing;
+                    isDead = proc == null || proc.isCrashing();
                 }
             } else {
                 final ProcessRecord proc = mService.mProcessNames.get(
@@ -1210,7 +1210,7 @@
                     + " (uid " + r.callingUid + ")");
             skip = true;
         }
-        if (r.curApp != null && r.curApp.crashing) {
+        if (r.curApp != null && r.curApp.isCrashing()) {
             // If the target process is crashing, just skip it.
             Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
                     + " to " + r.curApp + ": process crashing");
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index fb55a47..657e0eb 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -19,6 +19,13 @@
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static android.view.WindowManager.TRANSIT_UNSET;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
@@ -27,15 +34,7 @@
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED;
 import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
-import static android.view.WindowManager.TRANSIT_UNSET;
 
-import android.app.ActivityTaskManagerInternal.SleepToken;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
@@ -44,6 +43,7 @@
 
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java
index 9348023..6e42aee 100644
--- a/services/core/java/com/android/server/am/NativeCrashListener.java
+++ b/services/core/java/com/android/server/am/NativeCrashListener.java
@@ -29,7 +29,6 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.InterruptedIOException;
-import java.net.InetSocketAddress;
 
 /**
  * Set up a Unix domain socket that debuggerd will connect() to in
@@ -226,7 +225,7 @@
                 }
                 if (pr != null) {
                     // Don't attempt crash reporting for persistent apps
-                    if (pr.persistent) {
+                    if (pr.isPersistent()) {
                         if (DEBUG) {
                             Slog.v(TAG, "Skipping report for persistent app " + pr);
                         }
@@ -260,7 +259,7 @@
                     // even though the process will vanish as soon as we let
                     // debuggerd proceed.
                     synchronized (mAm) {
-                        pr.crashing = true;
+                        pr.setCrashing(true);
                         pr.forceCrashReport = true;
                     }
 
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index caf52e3..5a44ab6 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -54,7 +54,7 @@
  * Full information about a particular process that
  * is currently running.
  */
-final class ProcessRecord {
+final class ProcessRecord implements WindowProcessListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessRecord" : TAG_AM;
 
     private final ActivityManagerService mService; // where we came from
@@ -65,7 +65,37 @@
     final int userId;           // user of process.
     final String processName;   // name of the process
     // List of packages running in the process
-    final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
+    final PackageList pkgList = new PackageList();
+    final class PackageList {
+        final ArrayMap<String, ProcessStats.ProcessStateHolder> mPkgList = new ArrayMap<>();
+
+        ProcessStats.ProcessStateHolder put(String key, ProcessStats.ProcessStateHolder value) {
+            mWindowProcessController.addPackage(key);
+            return mPkgList.put(key, value);
+        }
+
+        void clear() {
+            mPkgList.clear();
+            mWindowProcessController.clearPackageList();
+        }
+
+        int size() {
+            return mPkgList.size();
+        }
+
+        String keyAt(int index) {
+            return mPkgList.keyAt(index);
+        }
+
+        public ProcessStats.ProcessStateHolder valueAt(int index) {
+            return mPkgList.valueAt(index);
+        }
+
+        boolean containsKey(Object key) {
+            return mPkgList.containsKey(key);
+        }
+    }
+
     final ProcessList.ProcStateMemTracker procStateMemTracker
             = new ProcessList.ProcStateMemTracker();
     UidRecord uidRecord;        // overall state of process's uid.
@@ -78,7 +108,7 @@
     int pid;                    // The process of this application; 0 if none
     String procStatFile;        // path to /proc/<pid>/stat
     int[] gids;                 // The gids this process was launched with
-    String requiredAbi;         // The ABI this process was launched with
+    private String mRequiredAbi;// The ABI this process was launched with
     String instructionSet;      // The instruction set this process was launched with
     boolean starting;           // True if the process is being started
     long lastActivityTime;      // For managing the LRU list
@@ -96,12 +126,11 @@
     int curAdj;                 // Current OOM adjustment for this process
     int setAdj;                 // Last set OOM adjustment for this process
     int verifiedAdj;            // The last adjustment that was verified as actually being set
-    int curSchedGroup;          // Currently desired scheduling class
+    private int mCurSchedGroup; // Currently desired scheduling class
     int setSchedGroup;          // Last set to background scheduling class
-    int vrThreadTid;            // Thread currently set for VR scheduling
     int trimMemoryLevel;        // Last selected memory trimming level
     int curProcState = PROCESS_STATE_NONEXISTENT; // Currently computed process state
-    int repProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state
+    private int mRepProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state
     int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker
     int pssProcState = PROCESS_STATE_NONEXISTENT; // Currently requesting pss for
     int pssStatType;            // The type of stat collection that we are currently requesting
@@ -112,7 +141,7 @@
     boolean notCachedSinceIdle; // Has this process not been in a cached state since last idle?
     boolean hasClientActivities;  // Are there any client services with activities?
     boolean hasStartedServices; // Are there any started services running in this process?
-    boolean foregroundServices; // Running any services that are foreground?
+    private boolean mHasForegroundServices; // Running any services that are foreground?
     boolean foregroundActivities; // Running any activities that are foreground?
     boolean repForegroundActivities; // Last reported foreground activities.
     boolean systemNoUi;         // This is a system process, but not currently showing UI.
@@ -173,10 +202,8 @@
     Object adjTarget;           // Debugging: target component impacting oom_adj.
     Runnable crashHandler;      // Optional local handler to be invoked in the process crash.
 
-    // all activities running in the process
-    final ArrayList<ActivityRecord> activities = new ArrayList<>();
-    // any tasks this process had run root activities in
-    final ArrayList<TaskRecord> recentTasks = new ArrayList<>();
+    // Controller for driving the process state on the window manager side.
+    final private WindowProcessController mWindowProcessController;
     // all ServiceRecord running in this process
     final ArraySet<ServiceRecord> services = new ArraySet<>();
     // services that are currently executing code (need to remain foreground).
@@ -194,11 +221,11 @@
     String[] isolatedEntryPointArgs; // Arguments to pass to isolatedEntryPoint's main().
 
     boolean execServicesFg;     // do we need to be executing services in the foreground?
-    boolean persistent;         // always keep this application running?
-    boolean crashing;           // are we in the process of crashing?
+    private boolean mPersistent;// always keep this application running?
+    private boolean mCrashing;  // are we in the process of crashing?
     Dialog crashDialog;         // dialog being displayed due to crash.
     boolean forceCrashReport;   // suppress normal auto-dismiss of crash dialog & report UI?
-    boolean notResponding;      // does the app have a not responding dialog?
+    private boolean mNotResponding; // does the app have a not responding dialog?
     Dialog anrDialog;           // dialog being displayed due to app not resp.
     boolean removed;            // has app package been removed from device?
     boolean debugging;          // was app launched for debugging?
@@ -259,7 +286,7 @@
             }
         }
         pw.println("}");
-        pw.print(prefix); pw.print("requiredAbi="); pw.print(requiredAbi);
+        pw.print(prefix); pw.print("mRequiredAbi="); pw.print(mRequiredAbi);
                 pw.print(" instructionSet="); pw.println(instructionSet);
         if (info.className != null) {
             pw.print(prefix); pw.print("class="); pw.println(info.className);
@@ -324,15 +351,12 @@
                 pw.print(" setRaw="); pw.print(setRawAdj);
                 pw.print(" cur="); pw.print(curAdj);
                 pw.print(" set="); pw.println(setAdj);
-        pw.print(prefix); pw.print("curSchedGroup="); pw.print(curSchedGroup);
+        pw.print(prefix); pw.print("mCurSchedGroup="); pw.print(mCurSchedGroup);
                 pw.print(" setSchedGroup="); pw.print(setSchedGroup);
                 pw.print(" systemNoUi="); pw.print(systemNoUi);
                 pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);
-        if (vrThreadTid != 0) {
-            pw.print(prefix); pw.print("vrThreadTid="); pw.println(vrThreadTid);
-        }
         pw.print(prefix); pw.print("curProcState="); pw.print(curProcState);
-                pw.print(" repProcState="); pw.print(repProcState);
+                pw.print(" mRepProcState="); pw.print(mRepProcState);
                 pw.print(" pssProcState="); pw.print(pssProcState);
                 pw.print(" setProcState="); pw.print(setProcState);
                 pw.print(" lastStateTime=");
@@ -349,8 +373,8 @@
                     pw.print(" hasOverlayUi="); pw.print(hasOverlayUi);
                     pw.print(" runningRemoteAnimation="); pw.println(runningRemoteAnimation);
         }
-        if (foregroundServices || forcingToImportant != null) {
-            pw.print(prefix); pw.print("foregroundServices="); pw.print(foregroundServices);
+        if (mHasForegroundServices || forcingToImportant != null) {
+            pw.print(prefix); pw.print("mHasForegroundServices="); pw.print(mHasForegroundServices);
                     pw.print(" forcingToImportant="); pw.println(forcingToImportant);
         }
         if (reportedInteraction || fgInteractionTime != 0) {
@@ -366,8 +390,8 @@
             }
             pw.println();
         }
-        if (persistent || removed) {
-            pw.print(prefix); pw.print("persistent="); pw.print(persistent);
+        if (mPersistent || removed) {
+            pw.print(prefix); pw.print("persistent="); pw.print(mPersistent);
                     pw.print(" removed="); pw.println(removed);
         }
         if (hasClientActivities || foregroundActivities || repForegroundActivities) {
@@ -407,16 +431,16 @@
                     pw.print(" killedByAm="); pw.print(killedByAm);
                     pw.print(" waitingToKill="); pw.println(waitingToKill);
         }
-        if (debugging || crashing || crashDialog != null || notResponding
+        if (debugging || mCrashing || crashDialog != null || mNotResponding
                 || anrDialog != null || bad) {
             pw.print(prefix); pw.print("debugging="); pw.print(debugging);
-                    pw.print(" crashing="); pw.print(crashing);
+                    pw.print(" mCrashing="); pw.print(mCrashing);
                     pw.print(" "); pw.print(crashDialog);
-                    pw.print(" notResponding="); pw.print(notResponding);
+                    pw.print(" mNotResponding="); pw.print(mNotResponding);
                     pw.print(" " ); pw.print(anrDialog);
                     pw.print(" bad="); pw.print(bad);
 
-                    // crashing or notResponding is always set before errorReportReceiver
+                    // mCrashing or mNotResponding is always set before errorReportReceiver
                     if (errorReportReceiver != null) {
                         pw.print(" errorReportReceiver=");
                         pw.print(errorReportReceiver.flattenToShortString());
@@ -431,18 +455,7 @@
             pw.print(prefix); pw.print("isolatedEntryPointArgs=");
             pw.println(Arrays.toString(isolatedEntryPointArgs));
         }
-        if (activities.size() > 0) {
-            pw.print(prefix); pw.println("Activities:");
-            for (int i=0; i<activities.size(); i++) {
-                pw.print(prefix); pw.print("  - "); pw.println(activities.get(i));
-            }
-        }
-        if (recentTasks.size() > 0) {
-            pw.print(prefix); pw.println("Recent Tasks:");
-            for (int i=0; i<recentTasks.size(); i++) {
-                pw.print(prefix); pw.print("  - "); pw.println(recentTasks.get(i));
-            }
-        }
+        mWindowProcessController.dump(pw, prefix);
         if (services.size() > 0) {
             pw.print(prefix); pw.println("Services:");
             for (int i=0; i<services.size(); i++) {
@@ -498,17 +511,20 @@
         uid = _uid;
         userId = UserHandle.getUserId(_uid);
         processName = _processName;
-        pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode));
         maxAdj = ProcessList.UNKNOWN_ADJ;
         curRawAdj = setRawAdj = ProcessList.INVALID_ADJ;
         curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ;
-        persistent = false;
+        mPersistent = false;
         removed = false;
         lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
+        mWindowProcessController = new WindowProcessController(
+                mService.mActivityTaskManager, info, processName, uid, userId, this, this);
+        pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode));
     }
 
     public void setPid(int _pid) {
         pid = _pid;
+        mWindowProcessController.setPid(pid);
         procStatFile = null;
         shortStringName = null;
         stringName = null;
@@ -519,7 +535,7 @@
             final ProcessState origBase = baseProcessTracker;
             if (origBase != null) {
                 origBase.setState(ProcessStats.STATE_NOTHING,
-                        tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList);
+                        tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList);
                 origBase.makeInactive();
             }
             baseProcessTracker = tracker.getProcessStateLocked(info.packageName, uid,
@@ -538,15 +554,17 @@
             }
         }
         thread = _thread;
+        mWindowProcessController.setThread(thread);
     }
 
     public void makeInactive(ProcessStatsService tracker) {
         thread = null;
+        mWindowProcessController.setThread(null);
         final ProcessState origBase = baseProcessTracker;
         if (origBase != null) {
             if (origBase != null) {
                 origBase.setState(ProcessStats.STATE_NOTHING,
-                        tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList);
+                        tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList);
                 origBase.makeInactive();
             }
             baseProcessTracker = null;
@@ -560,11 +578,24 @@
         }
     }
 
-    public void clearRecentTasks() {
-        for (int i = recentTasks.size() - 1; i >= 0; i--) {
-            recentTasks.get(i).clearRootProcess();
-        }
-        recentTasks.clear();
+    boolean hasActivities() {
+        return mWindowProcessController.hasActivities();
+    }
+
+    void clearActivities() {
+        mWindowProcessController.clearActivities();
+    }
+
+    boolean hasActivitiesOrRecentTasks() {
+        return mWindowProcessController.hasActivitiesOrRecentTasks();
+    }
+
+    boolean hasRecentTasks() {
+        return mWindowProcessController.hasRecentTasks();
+    }
+
+    void clearRecentTasks() {
+        mWindowProcessController.clearRecentTasks();
     }
 
     /**
@@ -572,12 +603,8 @@
      * to the user. See HistoryRecord.isInterestingToUserLocked()
      */
     public boolean isInterestingToUserLocked() {
-        final int size = activities.size();
-        for (int i = 0 ; i < size ; i++) {
-            ActivityRecord r = activities.get(i);
-            if (r.isInterestingToUserLocked()) {
-                return true;
-            }
+        if (mWindowProcessController.isInterestingToUser()) {
+            return true;
         }
 
         final int servicesSize = services.size();
@@ -590,14 +617,6 @@
         return false;
     }
 
-    public void stopFreezingAllLocked() {
-        int i = activities.size();
-        while (i > 0) {
-            i--;
-            activities.get(i).stopFreezingScreenLocked(true);
-        }
-    }
-
     public void unlinkDeathRecipient() {
         if (deathRecipient != null && thread != null) {
             thread.asBinder().unlinkToDeath(deathRecipient, 0);
@@ -676,7 +695,7 @@
             } else {
                 pendingStart = false;
             }
-            if (!persistent) {
+            if (!mPersistent) {
                 killed = true;
                 killedByAm = true;
             }
@@ -697,7 +716,7 @@
                 proto.write(ProcessRecordProto.ISOLATED_APP_ID, UserHandle.getAppId(uid));
             }
         }
-        proto.write(ProcessRecordProto.PERSISTENT, persistent);
+        proto.write(ProcessRecordProto.PERSISTENT, mPersistent);
         proto.end(token);
     }
 
@@ -806,8 +825,8 @@
     }
 
     public void forceProcessStateUpTo(int newState) {
-        if (repProcState > newState) {
-            curProcState = repProcState = newState;
+        if (mRepProcState > newState) {
+            curProcState = mRepProcState = newState;
         }
     }
 
@@ -819,7 +838,7 @@
         if (baseProcessTracker != null) {
             long now = SystemClock.uptimeMillis();
             baseProcessTracker.setState(ProcessStats.STATE_NOTHING,
-                    tracker.getMemFactorLocked(), now, pkgList);
+                    tracker.getMemFactorLocked(), now, pkgList.mPkgList);
             if (N != 1) {
                 for (int i=0; i<N; i++) {
                     ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i);
@@ -856,4 +875,128 @@
         }
         return list;
     }
+
+    WindowProcessController getWindowProcessController() {
+        return mWindowProcessController;
+    }
+
+    void setCurrentSchedulingGroup(int curSchedGroup) {
+        mCurSchedGroup = curSchedGroup;
+        mWindowProcessController.setCurrentSchedulingGroup(curSchedGroup);
+    }
+
+    int getCurrentSchedulingGroup() {
+        return mCurSchedGroup;
+    }
+
+    void setReportedProcState(int repProcState) {
+        mRepProcState = repProcState;
+        mWindowProcessController.setReportedProcState(repProcState);
+    }
+
+    int getReportedProcState() {
+        return mRepProcState;
+    }
+
+    void setCrashing(boolean crashing) {
+        mCrashing = crashing;
+        mWindowProcessController.setCrashing(crashing);
+    }
+
+    boolean isCrashing() {
+        return mCrashing;
+    }
+
+    void setNotResponding(boolean notResponding) {
+        mNotResponding = notResponding;
+        mWindowProcessController.setNotResponding(notResponding);
+    }
+
+    boolean isNotResponding() {
+        return mNotResponding;
+    }
+
+    void setPersistent(boolean persistent) {
+        mPersistent = persistent;
+        mWindowProcessController.setPersistent(persistent);
+    }
+
+    boolean isPersistent() {
+        return mPersistent;
+    }
+
+    public void setRequiredAbi(String requiredAbi) {
+        mRequiredAbi = requiredAbi;
+        mWindowProcessController.setRequiredAbi(requiredAbi);
+    }
+
+    String getRequiredAbi() {
+        return mRequiredAbi;
+    }
+
+    void setHasForegroundServices(boolean hasForegroundServices) {
+        mHasForegroundServices = hasForegroundServices;
+        mWindowProcessController.setHasForegroundServices(hasForegroundServices);
+    }
+
+    boolean hasForegroundServices() {
+        return mHasForegroundServices;
+    }
+
+    @Override
+    public void clearProfilerIfNeeded() {
+        synchronized (mService) {
+            if (mService.mProfileProc == null || mService.mProfilerInfo == null
+                    || mService.mProfileProc != this) {
+                return;
+            }
+            mService.clearProfilerLocked();
+        }
+    }
+
+    @Override
+    public void updateServiceConnectionActivities() {
+        synchronized (mService) {
+            mService.mServices.updateServiceConnectionActivitiesLocked(this);
+        }
+    }
+
+    @Override
+    public void setPendingUiClean(boolean pendingUiClean) {
+        synchronized (mService) {
+            this.pendingUiClean = true;
+        }
+    }
+
+    @Override
+    public void setPendingUiCleanAndForceProcessStateUpTo(int newState) {
+        synchronized (mService) {
+            pendingUiClean = true;
+            forceProcessStateUpTo(newState);
+        }
+    }
+
+    @Override
+    public void updateProcessInfo(boolean updateServiceConnectionActivities, boolean updateLru,
+            boolean activityChange, boolean updateOomAdj) {
+        synchronized (mService) {
+            if (updateServiceConnectionActivities) {
+                mService.mServices.updateServiceConnectionActivitiesLocked(this);
+            }
+            if (updateLru) {
+                mService.updateLruProcessLocked(this, activityChange, null);
+            }
+            if (updateOomAdj) {
+                mService.updateOomAdjLocked();
+            }
+        }
+    }
+
+    @Override
+    public void setRemoved(boolean removed) {
+        synchronized (mService) {
+            this.removed = removed;
+        }
+    }
+
 }
diff --git a/services/core/java/com/android/server/am/ProviderMap.java b/services/core/java/com/android/server/am/ProviderMap.java
index 2f52002..29c1657 100644
--- a/services/core/java/com/android/server/am/ProviderMap.java
+++ b/services/core/java/com/android/server/am/ProviderMap.java
@@ -32,7 +32,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -203,7 +202,7 @@
                         && (filterByClasses == null
                             || filterByClasses.contains(provider.name.getClassName())));
             if (sameComponent
-                    && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
+                    && (provider.proc == null || evenPersistent || !provider.proc.isPersistent())) {
                 if (!doit) {
                     return true;
                 }
diff --git a/services/core/java/com/android/server/am/SafeActivityOptions.java b/services/core/java/com/android/server/am/SafeActivityOptions.java
index b87b948..fef3b86 100644
--- a/services/core/java/com/android/server/am/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/am/SafeActivityOptions.java
@@ -117,7 +117,7 @@
      * @param callerApp The record of the caller.
      */
     ActivityOptions getOptions(@Nullable Intent intent, @Nullable ActivityInfo aInfo,
-            @Nullable ProcessRecord callerApp,
+            @Nullable WindowProcessController callerApp,
             ActivityStackSupervisor supervisor) throws SecurityException {
         if (mOriginalOptions != null) {
             checkPermissions(intent, aInfo, callerApp, supervisor, mOriginalOptions,
@@ -186,7 +186,7 @@
     }
 
     private void checkPermissions(@Nullable Intent intent, @Nullable ActivityInfo aInfo,
-            @Nullable ProcessRecord callerApp, ActivityStackSupervisor supervisor,
+            @Nullable WindowProcessController callerApp, ActivityStackSupervisor supervisor,
             ActivityOptions options, int callingPid, int callingUid) {
         // If a launch task id is specified, then ensure that the caller is the recents
         // component or has the START_TASKS_FROM_RECENTS permission
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index ba012ab..c8ffdb1 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -264,7 +264,7 @@
     /** The process that had previously hosted the root activity of this task.
      * Used to know that we should try harder to keep this process around, in case the
      * user wants to return to it. */
-    private ProcessRecord mRootProcess;
+    private WindowProcessController mRootProcess;
 
     /** Takes on same value as first root activity */
     boolean isPersistable = false;
@@ -1131,7 +1131,7 @@
                 // activity
                 reportOut.numRunning = 0;
             }
-            if (r.app != null && r.app.thread != null) {
+            if (r.attachedToProcess()) {
                 // Increment the number of actually running activities
                 reportOut.numRunning++;
             }
@@ -1909,18 +1909,18 @@
         }
     }
 
-    void setRootProcess(ProcessRecord proc) {
+    void setRootProcess(WindowProcessController proc) {
         clearRootProcess();
         if (intent != null &&
                 (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
             mRootProcess = proc;
-            proc.recentTasks.add(this);
+            mRootProcess.addRecentTask(this);
         }
     }
 
     void clearRootProcess() {
         if (mRootProcess != null) {
-            mRootProcess.recentTasks.remove(this);
+            mRootProcess.removeRecentTask(this);
             mRootProcess = null;
         }
     }
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 3b47844..992179a 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -41,7 +41,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
-import android.app.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.Dialog;
diff --git a/services/core/java/com/android/server/am/VrController.java b/services/core/java/com/android/server/am/VrController.java
index 45410d7..366f95a 100644
--- a/services/core/java/com/android/server/am/VrController.java
+++ b/services/core/java/com/android/server/am/VrController.java
@@ -147,14 +147,15 @@
      *
      * <p>Note: This must be called with the global ActivityManagerService lock held.
      *
-     * @param proc is the ProcessRecord of the process that entered or left the TOP_APP scheduling
-     *        group.
+     * @param proc is the WindowProcessController of the process that entered or left the TOP_APP
+     *            scheduling group.
      */
-    public void onTopProcChangedLocked(ProcessRecord proc) {
-        if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
-            setVrRenderThreadLocked(proc.vrThreadTid, proc.curSchedGroup, true);
+    public void onTopProcChangedLocked(WindowProcessController proc) {
+        final int curSchedGroup = proc.getCurrentSchedulingGroup();
+        if (curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
+            setVrRenderThreadLocked(proc.mVrThreadTid, curSchedGroup, true);
         } else {
-            if (proc.vrThreadTid == mVrRenderThreadTid) {
+            if (proc.mVrThreadTid == mVrRenderThreadTid) {
                 clearVrRenderThreadLocked(true);
             }
         }
@@ -190,7 +191,7 @@
             changed = changeVrModeLocked(vrMode, record.app);
 
             if (record.app != null) {
-                processId = record.app.pid;
+                processId = record.app.getPid();
             }
         }
 
@@ -213,9 +214,9 @@
      *
      * @param tid the tid of the thread to set, or 0 to unset the current thread.
      * @param pid the pid of the process owning the thread to set.
-     * @param proc the ProcessRecord of the process owning the thread to set.
+     * @param proc the WindowProcessController of the process owning the thread to set.
      */
-    public void setVrThreadLocked(int tid, int pid, ProcessRecord proc) {
+    public void setVrThreadLocked(int tid, int pid, WindowProcessController proc) {
         if (hasPersistentVrFlagSet()) {
             Slog.w(TAG, "VR thread cannot be set in persistent VR mode!");
             return;
@@ -230,9 +231,9 @@
         if (!inVrMode()) {
             Slog.w(TAG, "VR thread cannot be set when not in VR mode!");
         } else {
-            setVrRenderThreadLocked(tid, proc.curSchedGroup, false);
+            setVrRenderThreadLocked(tid, proc.getCurrentSchedulingGroup(), false);
         }
-        proc.vrThreadTid = (tid > 0) ? tid : 0;
+        proc.mVrThreadTid = (tid > 0) ? tid : 0;
     }
 
     /**
@@ -280,11 +281,11 @@
      * <p>Note: This must be called with the global ActivityManagerService lock held.
      *
      * @param vrMode {@code true} if the system VR mode is being enabled.
-     * @param proc the ProcessRecord of the process enabling the system VR mode.
+     * @param proc the WindowProcessController of the process enabling the system VR mode.
      *
      * @return {@code true} if our state changed.
      */
-    private boolean changeVrModeLocked(boolean vrMode, ProcessRecord proc) {
+    private boolean changeVrModeLocked(boolean vrMode, WindowProcessController proc) {
         final int oldVrState = mVrState;
 
         // This is the only place where mVrState should have its FLAG_VR_MODE setting
@@ -299,8 +300,9 @@
 
         if (changed) {
             if (proc != null) {
-                if (proc.vrThreadTid > 0) {
-                    setVrRenderThreadLocked(proc.vrThreadTid, proc.curSchedGroup, false);
+                if (proc.mVrThreadTid > 0) {
+                    setVrRenderThreadLocked(
+                            proc.mVrThreadTid, proc.getCurrentSchedulingGroup(), false);
                 }
             } else {
               clearVrRenderThreadLocked(false);
diff --git a/services/core/java/com/android/server/am/WindowProcessController.java b/services/core/java/com/android/server/am/WindowProcessController.java
new file mode 100644
index 0000000..64a273e
--- /dev/null
+++ b/services/core/java/com/android/server/am/WindowProcessController.java
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
+
+import android.app.Activity;
+import android.app.ActivityTaskManager;
+import android.app.ActivityThread;
+import android.app.IApplicationThread;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.internal.app.HeavyWeightSwitcherActivity;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.util.function.pooled.PooledRunnable;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * The Activity Manager (AM) package manages the lifecycle of processes in the system through
+ * {@link ProcessRecord}. However, it is important for the Window Manager (WM) package to be aware
+ * of the processes and their state since it affects how WM manages windows and activities. This
+ * class that allows the {@link ProcessRecord} object in the AM package to communicate important
+ * changes to its state to the WM package in a structured way. WM package also uses
+ * {@link WindowProcessListener} to request changes to the process state on the AM side.
+ * Note that public calls into this class are assumed to be originating from outside the
+ * window manager so the window manager lock is held and appropriate permissions are checked before
+ * calls are allowed to proceed.
+ */
+public class WindowProcessController {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_AM;
+    private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
+
+    // all about the first app in the process
+    final ApplicationInfo mInfo;
+    final String mName;
+    final int mUid;
+    // The process of this application; 0 if none
+    private volatile int mPid;
+    // user of process.
+    final int mUserId;
+    // The owner of this window process controller object. Mainly for identification when we
+    // communicate back to the activity manager side.
+    public final Object mOwner;
+    // List of packages running in the process
+    final ArraySet<String> mPkgList = new ArraySet<>();
+    private final WindowProcessListener mListener;
+    private final ActivityTaskManagerService mAtm;
+    // The actual proc...  may be null only if 'persistent' is true (in which case we are in the
+    // process of launching the app)
+    private volatile IApplicationThread mThread;
+    // Currently desired scheduling class
+    private volatile int mCurSchedGroup;
+    // Last reported process state;
+    private volatile int mRepProcState = PROCESS_STATE_NONEXISTENT;
+    // are we in the process of crashing?
+    private volatile boolean mCrashing;
+    // does the app have a not responding dialog?
+    private volatile boolean mNotResponding;
+    // always keep this application running?
+    private volatile boolean mPersistent;
+    // The ABI this process was launched with
+    private volatile String mRequiredAbi;
+    // Running any services that are foreground?
+    private volatile boolean mHasForegroundServices;
+
+    // Thread currently set for VR scheduling
+    int mVrThreadTid;
+
+    // all activities running in the process
+    private final ArrayList<ActivityRecord> mActivities = new ArrayList<>();
+    // any tasks this process had run root activities in
+    private final ArrayList<TaskRecord> mRecentTasks = new ArrayList<>();
+
+    WindowProcessController(ActivityTaskManagerService atm, ApplicationInfo info, String name,
+            int uid, int userId, Object owner, WindowProcessListener listener) {
+        mInfo = info;
+        mName = name;
+        mUid = uid;
+        mUserId = userId;
+        mOwner = owner;
+        mListener = listener;
+        mAtm = atm;
+    }
+
+    public void setPid(int pid) {
+        mPid = pid;
+    }
+
+    int getPid() {
+        return mPid;
+    }
+
+    public void setThread(IApplicationThread thread) {
+        mThread = thread;
+    }
+
+    IApplicationThread getThread() {
+        return mThread;
+    }
+
+    boolean hasThread() {
+        return mThread != null;
+    }
+
+    public void setCurrentSchedulingGroup(int curSchedGroup) {
+        mCurSchedGroup = curSchedGroup;
+    }
+
+    int getCurrentSchedulingGroup() {
+        return mCurSchedGroup;
+    }
+
+    public void setReportedProcState(int repProcState) {
+        mRepProcState = repProcState;
+    }
+
+    int getReportedProcState() {
+        return mRepProcState;
+    }
+
+    public void setCrashing(boolean crashing) {
+        mCrashing = crashing;
+    }
+
+    boolean isCrashing() {
+        return mCrashing;
+    }
+
+    public void setNotResponding(boolean notResponding) {
+        mNotResponding = notResponding;
+    }
+
+    boolean isNotResponding() {
+        return mNotResponding;
+    }
+
+    public void setPersistent(boolean persistent) {
+        mPersistent = persistent;
+    }
+
+    boolean isPersistent() {
+        return mPersistent;
+    }
+
+    public void setHasForegroundServices(boolean hasForegroundServices) {
+        mHasForegroundServices = hasForegroundServices;
+    }
+
+    boolean hasForegroundServices() {
+        return mHasForegroundServices;
+    }
+
+    public void setRequiredAbi(String requiredAbi) {
+        mRequiredAbi = requiredAbi;
+    }
+
+    String getRequiredAbi() {
+        return mRequiredAbi;
+    }
+
+    public void addPackage(String packageName) {
+        synchronized (mAtm.mGlobalLock) {
+            mPkgList.add(packageName);
+        }
+    }
+
+    public void clearPackageList() {
+        synchronized (mAtm.mGlobalLock) {
+            mPkgList.clear();
+        }
+    }
+
+    void addActivityIfNeeded(ActivityRecord r) {
+        if (mActivities.contains(r)) {
+            return;
+        }
+        mActivities.add(r);
+    }
+
+    void removeActivity(ActivityRecord r) {
+        mActivities.remove(r);
+    }
+
+    public void clearActivities() {
+        synchronized (mAtm.mGlobalLock) {
+            mActivities.clear();
+        }
+    }
+
+    public boolean hasActivities() {
+        synchronized (mAtm.mGlobalLock) {
+            return !mActivities.isEmpty();
+        }
+    }
+
+    public boolean hasVisibleActivities() {
+        synchronized (mAtm.mGlobalLock) {
+            for (int i = mActivities.size() - 1; i >= 0; --i) {
+                final ActivityRecord r = mActivities.get(i);
+                if (r.visible) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public boolean hasActivitiesOrRecentTasks() {
+        synchronized (mAtm.mGlobalLock) {
+            return !mActivities.isEmpty() || !mRecentTasks.isEmpty();
+        }
+    }
+
+    public void stopFreezingActivities() {
+        synchronized (mAtm.mGlobalLock) {
+            int i = mActivities.size();
+            while (i > 0) {
+                i--;
+                mActivities.get(i).stopFreezingScreenLocked(true);
+            }
+        }
+    }
+
+    public void finishActivities() {
+        synchronized (mAtm.mGlobalLock) {
+            ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities);
+            for (int i = 0; i < activities.size(); i++) {
+                final ActivityRecord r = activities.get(i);
+                if (!r.finishing && r.isInStackLocked()) {
+                    r.getStack().finishActivityLocked(r, Activity.RESULT_CANCELED,
+                            null, "finish-heavy", true);
+                }
+            }
+        }
+    }
+
+    public boolean isInterestingToUser() {
+        synchronized (mAtm.mGlobalLock) {
+            final int size = mActivities.size();
+            for (int i = 0; i < size; i++) {
+                ActivityRecord r = mActivities.get(i);
+                if (r.isInterestingToUserLocked()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public boolean hasRunningActivity(String packageName) {
+        synchronized (mAtm.mGlobalLock) {
+            for (int i = mActivities.size() - 1; i >= 0; --i) {
+                final ActivityRecord r = mActivities.get(i);
+                if (packageName.equals(r.packageName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public void clearPackagePreferredForHomeActivities() {
+        synchronized (mAtm.mGlobalLock) {
+            for (int i = mActivities.size() - 1; i >= 0; --i) {
+                final ActivityRecord r = mActivities.get(i);
+                if (r.isActivityTypeHome()) {
+                    Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
+                    try {
+                        ActivityThread.getPackageManager()
+                                .clearPackagePreferredActivities(r.packageName);
+                    } catch (RemoteException c) {
+                        // pm is in same process, this will never happen.
+                    }
+                }
+            }
+        }
+    }
+
+    boolean hasStartedActivity(ActivityRecord launchedActivity) {
+        for (int i = mActivities.size() - 1; i >= 0; i--) {
+            final ActivityRecord activity = mActivities.get(i);
+            if (launchedActivity == activity) {
+                continue;
+            }
+            if (!activity.stopped) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    public void updateIntentForHeavyWeightActivity(Intent intent) {
+        synchronized (mAtm.mGlobalLock) {
+            if (mActivities.isEmpty()) {
+                return;
+            }
+            ActivityRecord hist = mActivities.get(0);
+            intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName);
+            intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTask().taskId);
+        }
+    }
+
+    boolean shouldKillProcessForRemovedTask(TaskRecord tr) {
+        for (int k = 0; k < mActivities.size(); k++) {
+            final TaskRecord otherTask = mActivities.get(k).getTask();
+            if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
+                // Don't kill process(es) that has an activity in a different task that is
+                // also in recents.
+                return false;
+            }
+        }
+        return true;
+    }
+
+    ArraySet<TaskRecord> getReleaseSomeActivitiesTasks() {
+        // Examine all activities currently running in the process.
+        TaskRecord firstTask = null;
+        // Tasks is non-null only if two or more tasks are found.
+        ArraySet<TaskRecord> tasks = null;
+        if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + this);
+        for (int i = 0; i < mActivities.size(); i++) {
+            final ActivityRecord r = mActivities.get(i);
+            // First, if we find an activity that is in the process of being destroyed,
+            // then we just aren't going to do anything for now; we want things to settle
+            // down before we try to prune more activities.
+            if (r.finishing || r.isState(DESTROYING, DESTROYED)) {
+                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Abort release; already destroying: " + r);
+                return null;
+            }
+            // Don't consider any activies that are currently not in a state where they
+            // can be destroyed.
+            if (r.visible || !r.stopped || !r.haveState
+                    || r.isState(RESUMED, PAUSING, PAUSED, STOPPING)) {
+                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
+                continue;
+            }
+
+            final TaskRecord task = r.getTask();
+            if (task != null) {
+                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + task
+                        + " from " + r);
+                if (firstTask == null) {
+                    firstTask = task;
+                } else if (firstTask != task) {
+                    if (tasks == null) {
+                        tasks = new ArraySet<>();
+                        tasks.add(firstTask);
+                    }
+                    tasks.add(task);
+                }
+            }
+        }
+
+        return tasks;
+    }
+
+    public interface ComputeOomAdjCallback {
+        void onVisibleActivity();
+        void onPausedActivity();
+        void onStoppingActivity(boolean finishing);
+        void onOtherActivity();
+    }
+
+    public int computeOomAdjFromActivities(int minTaskLayer, ComputeOomAdjCallback callback) {
+        synchronized (mAtm.mGlobalLock) {
+            final int activitiesSize = mActivities.size();
+            for (int j = 0; j < activitiesSize; j++) {
+                final ActivityRecord r = mActivities.get(j);
+                if (r.app != this) {
+                    Log.e(TAG, "Found activity " + r + " in proc activity list using " + r.app
+                            + " instead of expected " + this);
+                    if (r.app == null || (r.app.mUid == mUid)) {
+                        // Only fix things up when they look sane
+                        r.setProcess(this);
+                    } else {
+                        continue;
+                    }
+                }
+                if (r.visible) {
+                    callback.onVisibleActivity();
+                    final TaskRecord task = r.getTask();
+                    if (task != null && minTaskLayer > 0) {
+                        final int layer = task.mLayerRank;
+                        if (layer >= 0 && minTaskLayer > layer) {
+                            minTaskLayer = layer;
+                        }
+                    }
+                    break;
+                } else if (r.isState(PAUSING, PAUSED)) {
+                    callback.onPausedActivity();
+                } else if (r.isState(STOPPING)) {
+                    callback.onStoppingActivity(r.finishing);
+                } else {
+                    callback.onOtherActivity();
+                }
+            }
+        }
+
+        return minTaskLayer;
+    }
+
+    void clearProfilerIfNeeded() {
+        if (mListener == null) return;
+        // Posting on handler so WM lock isn't held when we call into AM.
+        mAtm.mH.post(() -> mListener.clearProfilerIfNeeded());
+    }
+
+    void updateProcessInfo(boolean updateServiceConnectionActivities, boolean updateLru,
+            boolean activityChange, boolean updateOomAdj) {
+        if (mListener == null) return;
+        // Posting on handler so WM lock isn't held when we call into AM.
+        final Runnable r = PooledLambda.obtainRunnable(WindowProcessListener::updateProcessInfo,
+                mListener, updateServiceConnectionActivities, updateLru, activityChange,
+                updateOomAdj);
+        mAtm.mH.post(r);
+    }
+
+    void updateServiceConnectionActivities() {
+        if (mListener == null) return;
+        // Posting on handler so WM lock isn't held when we call into AM.
+        mAtm.mH.post(() -> mListener.updateServiceConnectionActivities());
+    }
+
+    void setPendingUiClean(boolean pendingUiClean) {
+        if (mListener == null) return;
+        // Posting on handler so WM lock isn't held when we call into AM.
+        final Runnable r = PooledLambda.obtainRunnable(
+                WindowProcessListener::setPendingUiClean, mListener, pendingUiClean);
+        mAtm.mH.post(r);
+    }
+
+    void setPendingUiCleanAndForceProcessStateUpTo(int newState) {
+        if (mListener == null) return;
+        // Posting on handler so WM lock isn't held when we call into AM.
+        final Runnable r = PooledLambda.obtainRunnable(
+                WindowProcessListener::setPendingUiCleanAndForceProcessStateUpTo,
+                mListener, newState);
+        mAtm.mH.post(r);
+    }
+
+    void setRemoved(boolean removed) {
+        if (mListener == null) return;
+        // Posting on handler so WM lock isn't held when we call into AM.
+        final Runnable r = PooledLambda.obtainRunnable(
+                WindowProcessListener::setRemoved, mListener, removed);
+        mAtm.mH.post(r);
+    }
+
+    void addRecentTask(TaskRecord task) {
+        mRecentTasks.add(task);
+    }
+
+    void removeRecentTask(TaskRecord task) {
+        mRecentTasks.remove(task);
+    }
+
+    public boolean hasRecentTasks() {
+        synchronized (mAtm.mGlobalLock) {
+            return !mRecentTasks.isEmpty();
+        }
+    }
+
+    public void clearRecentTasks() {
+        synchronized (mAtm.mGlobalLock) {
+            for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+                mRecentTasks.get(i).clearRootProcess();
+            }
+            mRecentTasks.clear();
+        }
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        synchronized (mAtm.mGlobalLock) {
+            if (mActivities.size() > 0) {
+                pw.print(prefix); pw.println("Activities:");
+                for (int i = 0; i < mActivities.size(); i++) {
+                    pw.print(prefix); pw.print("  - "); pw.println(mActivities.get(i));
+                }
+            }
+
+            if (mRecentTasks.size() > 0) {
+                pw.println(prefix + "Recent Tasks:");
+                for (int i = 0; i < mRecentTasks.size(); i++) {
+                    pw.println(prefix + "  - " + mRecentTasks.get(i));
+                }
+            }
+
+            if (mVrThreadTid != 0) {
+                pw.print(prefix); pw.print("mVrThreadTid="); pw.println(mVrThreadTid);
+            }
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/am/WindowProcessListener.java b/services/core/java/com/android/server/am/WindowProcessListener.java
new file mode 100644
index 0000000..92e4461
--- /dev/null
+++ b/services/core/java/com/android/server/am/WindowProcessListener.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+/**
+ * Interface used by the owner/creator of a process that owns windows to listen to changes from the
+ * WM side.
+ * @see WindowProcessController
+ */
+public interface WindowProcessListener {
+
+    /** Clear the profiler record if we are currently profiling this process. */
+    void clearProfilerIfNeeded();
+
+    /** Update the service connection for this process based on activities it might have. */
+    void updateServiceConnectionActivities();
+
+    /** Set or clear flag that we would like to clean-up UI resources for this process. */
+    void setPendingUiClean(boolean pendingUiClean);
+
+    /**
+     * Set flag that we would like to clean-up UI resources for this process and force new process
+     * state.
+     */
+    void setPendingUiCleanAndForceProcessStateUpTo(int newState);
+
+    /** Update the process information. */
+    void updateProcessInfo(boolean updateServiceConnectionActivities, boolean updateLru,
+            boolean activityChange, boolean updateOomAdj);
+
+    /** Set process package been removed from device. */
+    void setRemoved(boolean removed);
+}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 571ee42..6971f71 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -20,8 +20,6 @@
 import static android.media.AudioManager.RINGER_MODE_NORMAL;
 import static android.media.AudioManager.RINGER_MODE_SILENT;
 import static android.media.AudioManager.RINGER_MODE_VIBRATE;
-import static android.media.AudioManager.STREAM_ALARM;
-import static android.media.AudioManager.STREAM_MUSIC;
 import static android.media.AudioManager.STREAM_SYSTEM;
 import static android.os.Process.FIRST_APPLICATION_UID;
 import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
@@ -33,7 +31,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.IUidObserver;
@@ -142,6 +139,7 @@
 import com.android.server.audio.AudioServiceEvents.VolumeEvent;
 import com.android.server.audio.AudioServiceEvents.WiredDevConnectEvent;
 import com.android.server.pm.UserManagerService;
+import com.android.server.wm.ActivityTaskManagerInternal;
 
 import org.xmlpull.v1.XmlPullParserException;
 
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 079f3ea..65ccecd 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -21,7 +21,6 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
-import android.app.ActivityTaskManagerInternal;
 import android.app.AppOpsManager;
 import android.app.IApplicationThread;
 import android.content.ComponentName;
@@ -42,6 +41,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
+import com.android.server.wm.ActivityTaskManagerInternal;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index a52470d..9323040 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -20,7 +20,6 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
 import android.app.IApplicationThread;
 import android.app.PendingIntent;
@@ -64,6 +63,7 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.wm.ActivityTaskManagerInternal;
 
 import java.util.Collections;
 import java.util.List;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2a4a976..9a15623 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -90,7 +90,6 @@
 import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDWR;
-
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
 import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
@@ -121,7 +120,6 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.ResourcesManager;
@@ -321,11 +319,7 @@
 import com.android.server.pm.permission.PermissionsState.PermissionState;
 import com.android.server.security.VerityUtils;
 import com.android.server.storage.DeviceStorageMonitorInternal;
-
-import dalvik.system.CloseGuard;
-import dalvik.system.VMRuntime;
-
-import libcore.io.IoUtils;
+import com.android.server.wm.ActivityTaskManagerInternal;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -371,6 +365,10 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Predicate;
 
+import dalvik.system.CloseGuard;
+import dalvik.system.VMRuntime;
+import libcore.io.IoUtils;
+
 /**
  * Keep track of all those APKs everywhere.
  * <p>
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 6e7eae1..46935f0 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -27,7 +27,6 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
-import android.app.ActivityTaskManagerInternal;
 import android.app.IActivityManager;
 import android.app.IStopUserCallback;
 import android.app.KeyguardManager;
@@ -99,8 +98,7 @@
 import com.android.server.SystemService;
 import com.android.server.am.UserState;
 import com.android.server.storage.DeviceStorageMonitorInternal;
-
-import libcore.io.IoUtils;
+import com.android.server.wm.ActivityTaskManagerInternal;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -123,6 +121,8 @@
 import java.util.List;
 import java.util.Objects;
 
+import libcore.io.IoUtils;
+
 /**
  * Service for {@link UserManager}.
  *
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 71e342e..b99f8d6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -124,7 +124,6 @@
 import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
 import static android.view.WindowManagerGlobal.ADD_OKAY;
 import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
-
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
@@ -155,8 +154,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
-import android.app.ActivityTaskManagerInternal.SleepToken;
 import android.app.ActivityTaskManager;
 import android.app.ActivityThread;
 import android.app.AppOpsManager;
@@ -275,8 +272,8 @@
 import com.android.internal.policy.PhoneWindow;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.ScreenshotHelper;
 import com.android.internal.util.ScreenShapeHelper;
+import com.android.internal.util.ScreenshotHelper;
 import com.android.internal.widget.PointerLocationView;
 import com.android.server.GestureLauncherService;
 import com.android.server.LocalServices;
@@ -286,6 +283,8 @@
 import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
 import com.android.server.wm.AppTransition;
 import com.android.server.wm.DisplayFrames;
 import com.android.server.wm.WindowManagerInternal;
diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java
index 9183b08..a16dbb7 100644
--- a/services/core/java/com/android/server/vr/Vr2dDisplay.java
+++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java
@@ -3,9 +3,7 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.app.Vr2dDisplayProperties;
-import android.app.Service;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -14,19 +12,15 @@
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
 import android.media.ImageReader;
-import android.os.Build;
 import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.service.vr.IPersistentVrStateCallbacks;
 import android.service.vr.IVrManager;
 import android.util.Log;
 import android.view.Surface;
 
 import com.android.server.LocalServices;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
 /**
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 50bf57f..5c45afc 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -18,15 +18,13 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.Manifest;
-import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
-import android.app.ActivityTaskManagerInternal.ScreenObserver;
+import android.annotation.NonNull;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.INotificationManager;
-import android.app.Vr2dDisplayProperties;
 import android.app.NotificationManager;
-import android.annotation.NonNull;
+import android.app.Vr2dDisplayProperties;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -60,30 +58,30 @@
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
-
-import com.android.server.FgThread;
-import com.android.server.wm.WindowManagerInternal;
 import android.view.inputmethod.InputMethodManagerInternal;
 
 import com.android.internal.R;
 import com.android.internal.util.DumpUtils;
+import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 import com.android.server.SystemService;
-import com.android.server.utils.ManagedApplicationService.PendingEvent;
-import com.android.server.utils.ManagedApplicationService.LogEvent;
-import com.android.server.utils.ManagedApplicationService.LogFormattable;
-import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
 import com.android.server.utils.ManagedApplicationService;
 import com.android.server.utils.ManagedApplicationService.BinderChecker;
+import com.android.server.utils.ManagedApplicationService.LogEvent;
+import com.android.server.utils.ManagedApplicationService.LogFormattable;
+import com.android.server.utils.ManagedApplicationService.PendingEvent;
+import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
+import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
+import com.android.server.wm.WindowManagerInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.StringBuilder;
 import java.text.SimpleDateFormat;
-import java.util.Arrays;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
diff --git a/core/java/android/app/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
similarity index 95%
rename from core/java/android/app/ActivityTaskManagerInternal.java
rename to services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index fa78db5..3885cf9 100644
--- a/core/java/android/app/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -14,10 +14,13 @@
  * limitations under the License
  */
 
-package android.app;
+package com.android.server.wm;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.AppProtoEnums;
+import android.app.IActivityManager;
+import android.app.IApplicationThread;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Bundle;
@@ -28,6 +31,7 @@
 import android.view.RemoteAnimationAdapter;
 
 import com.android.internal.app.IVoiceInteractor;
+import com.android.server.am.WindowProcessController;
 
 import java.util.List;
 
@@ -210,11 +214,6 @@
      */
     public abstract void setFocusedActivity(IBinder token);
 
-    /**
-     * Returns {@code true} if {@code uid} is running an activity from {@code packageName}.
-     */
-    public abstract boolean hasRunningActivity(int uid, @Nullable String packageName);
-
     public abstract void registerScreenObserver(ScreenObserver observer);
 
     /**
@@ -263,4 +262,8 @@
      */
     public abstract void onUserStopped(int userId);
     public abstract boolean isGetTasksAllowed(String caller, int callingPid, int callingUid);
+
+    public abstract void onProcessAdded(WindowProcessController proc);
+    public abstract void onProcessRemoved(String name, int uid);
+    public abstract void onCleanUpApplicationRecord(WindowProcessController proc);
 }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index b610695..6f5fea9 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -16,13 +16,13 @@
 
 package com.android.server.wm;
 
-import static android.app.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
 import static com.android.server.wm.AnimationAdapterProto.REMOTE;
 import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
@@ -48,11 +48,14 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 import android.view.inputmethod.InputMethodManagerInternal;
+
+import com.google.android.collect.Sets;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 import com.android.server.wm.utils.InsetUtils;
-import com.google.android.collect.Sets;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d43338d..399078a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -117,7 +117,6 @@
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityTaskManager;
-import android.app.ActivityTaskManagerInternal;
 import android.app.ActivityThread;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 1a8753d..aced8e4 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -16,18 +16,10 @@
 
 package com.android.server.wm;
 
-import static android.app.ActivityTaskManagerInternal.APP_TRANSITION_SNAPSHOT;
-import static android.app.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
-import static android.app.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
-
-import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
-import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
@@ -39,10 +31,17 @@
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
 import static android.view.WindowManager.TRANSIT_WALLPAPER_CLOSE;
 import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
 import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
 import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SNAPSHOT;
+import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
+import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
 import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c3a8d6c..4456ed0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -563,11 +563,10 @@
         // TODO: Might need to move after migration to WM.
         ActivityTaskManagerService atm = mSystemServiceManager.startService(
                 ActivityTaskManagerService.Lifecycle.class).getService();
-        mActivityManagerService = mSystemServiceManager.startService(
-                ActivityManagerService.Lifecycle.class).getService();
+        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
+                mSystemServiceManager, atm);
         mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
         mActivityManagerService.setInstaller(installer);
-        mActivityManagerService.setActivityTaskManager(atm);
         traceEnd();
 
         // Power manager needs to be started early because other services need it.
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
index 077b455..583a9dd 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
@@ -50,7 +50,7 @@
 @RunWith(AndroidJUnit4.class)
 public class ActivityLaunchParamsModifierTests extends ActivityTestsBase {
     private ActivityLaunchParamsModifier mModifier;
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
     private ActivityStack mStack;
     private TaskRecord mTask;
     private ActivityRecord mActivity;
@@ -62,7 +62,7 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mService = createActivityManagerService();
+        mService = createActivityTaskManagerService();
         mModifier = new ActivityLaunchParamsModifier(mService.mStackSupervisor);
         mCurrent = new LaunchParams();
         mResult = new LaunchParams();
@@ -104,12 +104,12 @@
                 mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
 
         // Does not support freeform
-        mService.mActivityTaskManager.mSupportsFreeformWindowManagement = false;
+        mService.mSupportsFreeformWindowManagement = false;
         assertFalse(mService.mStackSupervisor.canUseActivityOptionsLaunchBounds(options));
         assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
                 mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
 
-        mService.mActivityTaskManager.mSupportsFreeformWindowManagement = true;
+        mService.mSupportsFreeformWindowManagement = true;
         options.setLaunchBounds(new Rect());
         assertTrue(mService.mStackSupervisor.canUseActivityOptionsLaunchBounds(options));
 
@@ -130,7 +130,7 @@
     public void testBoundsExtraction() throws Exception {
         // Make activity resizeable and enable freeform mode.
         mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
-        mService.mActivityTaskManager.mSupportsFreeformWindowManagement = true;
+        mService.mSupportsFreeformWindowManagement = true;
 
         ActivityOptions options = ActivityOptions.makeBasic();
         final Rect proposedBounds = new Rect(20, 30, 45, 40);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 3172323..dd3e5a8 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -73,7 +73,7 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityRecordTests extends ActivityTestsBase {
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
     private TestActivityStack mStack;
     private TaskRecord mTask;
     private ActivityRecord mActivity;
@@ -83,7 +83,7 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityManagerService();
+        mService = createActivityTaskManagerService();
         mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
@@ -126,7 +126,7 @@
                 pauseFound.value = true;
             }
             return null;
-        }).when(mActivity.app.thread).scheduleTransaction(any());
+        }).when(mActivity.app.getThread()).scheduleTransaction(any());
 
         mActivity.setState(STOPPED, "testPausingWhenVisibleFromStopped");
 
@@ -236,7 +236,7 @@
 
     private void testSupportsLaunchingResizeable(boolean taskPresent, boolean taskResizeable,
             boolean activityResizeable, boolean expected) {
-        mService.mActivityTaskManager.mSupportsMultiWindow = true;
+        mService.mSupportsMultiWindow = true;
 
         final TaskRecord task = taskPresent
                 ? new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build() : null;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 0674d85..a44661d 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -68,7 +68,7 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStackSupervisorTests extends ActivityTestsBase {
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
     private ActivityStackSupervisor mSupervisor;
     private ActivityStack mFullscreenStack;
 
@@ -77,7 +77,7 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityManagerService();
+        mService = createActivityTaskManagerService();
         mSupervisor = mService.mStackSupervisor;
         mFullscreenStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
@@ -278,7 +278,7 @@
         assertEquals(originalStackCount + 1, defaultDisplay.getChildCount());
 
         // Let's pretend that the app has crashed.
-        firstActivity.app.thread = null;
+        firstActivity.app.setThread(null);
         mService.mStackSupervisor.finishTopCrashedActivitiesLocked(firstActivity.app, "test");
 
         // Verify that the stack was removed.
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 01425ed..0d0a6ba 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -61,7 +61,7 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStackTests extends ActivityTestsBase {
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
     private ActivityStackSupervisor mSupervisor;
     private ActivityDisplay mDefaultDisplay;
     private ActivityStack mStack;
@@ -72,7 +72,7 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityManagerService();
+        mService = createActivityTaskManagerService();
         mSupervisor = mService.mStackSupervisor;
         mDefaultDisplay = mService.mStackSupervisor.getDefaultDisplay();
         mStack = mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
index df31042..f5ae46cd 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
@@ -19,7 +19,9 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
+import android.app.IApplicationThread;
 import android.content.Intent;
+import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -49,7 +51,7 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStartControllerTests extends ActivityTestsBase {
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
     private ActivityStartController mController;
     private Factory mFactory;
     private ActivityStarter mStarter;
@@ -57,10 +59,10 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mService = createActivityManagerService();
+        mService = createActivityTaskManagerService();
         mFactory = mock(Factory.class);
-        mController = new ActivityStartController(mService.mActivityTaskManager, mService.mStackSupervisor, mFactory);
-        mStarter = spy(new ActivityStarter(mController, mService.mActivityTaskManager,
+        mController = new ActivityStartController(mService, mService.mStackSupervisor, mFactory);
+        mStarter = spy(new ActivityStarter(mController, mService,
                 mService.mStackSupervisor, mock(ActivityStartInterceptor.class)));
         doReturn(mStarter).when(mFactory).obtain();
     }
@@ -77,11 +79,14 @@
         final int startFlags = random.nextInt();
         final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        final ProcessRecord process= new ProcessRecord(null, null,
-                mService.mContext.getApplicationInfo(), "name", 12345);
+        final WindowProcessController wpc = new WindowProcessController(mService,
+                mService.mContext.getApplicationInfo(), "name", 12345,
+                UserHandle.getUserId(12345), mock(Object.class),
+                mock(WindowProcessListener.class));
+        wpc.setThread(mock(IApplicationThread.class));
 
         mController.addPendingActivityLaunch(
-                new PendingActivityLaunch(activity, source, startFlags, stack, process));
+                new PendingActivityLaunch(activity, source, startFlags, stack, wpc));
         final boolean resume = random.nextBoolean();
         mController.doPendingActivityLaunches(resume);
 
@@ -96,7 +101,7 @@
     @Test
     public void testRecycling() throws Exception {
         final Intent intent = new Intent();
-        final ActivityStarter optionStarter = new ActivityStarter(mController, mService.mActivityTaskManager,
+        final ActivityStarter optionStarter = new ActivityStarter(mController, mService,
                 mService.mStackSupervisor, mock(ActivityStartInterceptor.class));
         optionStarter
                 .setIntent(intent)
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index 274d9e5..267e689 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -88,7 +88,7 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStarterTests extends ActivityTestsBase {
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
     private ActivityStarter mStarter;
     private ActivityStartController mController;
 
@@ -107,9 +107,9 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mService = createActivityManagerService();
+        mService = createActivityTaskManagerService();
         mController = mock(ActivityStartController.class);
-        mStarter = new ActivityStarter(mController, mService.mActivityTaskManager, mService.mStackSupervisor,
+        mStarter = new ActivityStarter(mController, mService, mService.mStackSupervisor,
                 mock(ActivityStartInterceptor.class));
     }
 
@@ -134,7 +134,7 @@
         assertTrue(task2.getStack() instanceof PinnedActivityStack);
         mStarter.updateBounds(task2, bounds);
 
-        verify(mService.mActivityTaskManager, times(1)).resizeStack(eq(task2.getStack().mStackId),
+        verify(mService, times(1)).resizeStack(eq(task2.getStack().mStackId),
                 eq(bounds), anyBoolean(), anyBoolean(), anyBoolean(), anyInt());
 
         // In the case of no animation, the stack and task bounds should be set immediately.
@@ -189,20 +189,21 @@
      */
     private void verifyStartActivityPreconditions(int preconditions, int launchFlags,
             int expectedResult) {
-        final ActivityManagerService service = createActivityManagerService();
+        final ActivityTaskManagerService service = mService;
         final IPackageManager packageManager = mock(IPackageManager.class);
         final ActivityStartController controller = mock(ActivityStartController.class);
 
-        final ActivityStarter starter = new ActivityStarter(controller, service.mActivityTaskManager,
+        final ActivityStarter starter = new ActivityStarter(controller, service,
                 service.mStackSupervisor, mock(ActivityStartInterceptor.class));
+        prepareStarter(launchFlags);
         final IApplicationThread caller = mock(IApplicationThread.class);
 
         // If no caller app, return {@code null} {@link ProcessRecord}.
         final ProcessRecord record = containsConditions(preconditions, PRECONDITION_NO_CALLER_APP)
-                ? null : new ProcessRecord(null, mock(BatteryStatsImpl.class),
+                ? null : new ProcessRecord(service.mAm, mock(BatteryStatsImpl.class),
                 mock(ApplicationInfo.class), null, 0);
 
-        doReturn(record).when(service).getRecordForAppLocked(anyObject());
+        doReturn(record).when(service.mAm).getRecordForAppLocked(anyObject());
 
         final Intent intent = new Intent();
         intent.setFlags(launchFlags);
@@ -236,7 +237,7 @@
         }
 
         if (containsConditions(preconditions, PRECONDITION_DISALLOW_APP_SWITCHING)) {
-            doReturn(false).when(service.mActivityTaskManager).checkAppSwitchAllowedLocked(
+            doReturn(false).when(service).checkAppSwitchAllowedLocked(
                     anyInt(), anyInt(), anyInt(), anyInt(), any());
         }
 
@@ -282,7 +283,7 @@
 
         // Ensure that {@link ActivityOptions} are aborted with unsuccessful result.
         if (expectedResult != START_SUCCESS) {
-            final ActivityStarter optionStarter = new ActivityStarter(mController, mService.mActivityTaskManager,
+            final ActivityStarter optionStarter = new ActivityStarter(mController, mService,
                     mService.mStackSupervisor, mock(ActivityStartInterceptor.class));
             final ActivityOptions options = spy(ActivityOptions.makeBasic());
 
@@ -336,7 +337,7 @@
         info.applicationInfo = new ApplicationInfo();
         info.applicationInfo.packageName = ActivityBuilder.getDefaultComponent().getPackageName();
 
-        return new ActivityStarter(mController, mService.mActivityTaskManager,
+        return new ActivityStarter(mController, mService,
                 mService.mStackSupervisor, mock(ActivityStartInterceptor.class))
                 .setIntent(intent)
                 .setActivityInfo(info);
@@ -456,7 +457,7 @@
 
         final ActivityStarter starter = prepareStarter(0);
 
-        final LockTaskController lockTaskController = mService.mActivityTaskManager.getLockTaskController();
+        final LockTaskController lockTaskController = mService.getLockTaskController();
         doReturn(true).when(lockTaskController).isLockTaskModeViolation(any());
 
         final int result = starter.setReason("testTaskModeViolation").execute();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index dd30e70..1dd7b4c 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -51,6 +51,7 @@
 import android.hardware.display.DisplayManager;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionSession;
 import android.support.test.InstrumentationRegistry;
 import android.testing.DexmakerShareClassLoaderRule;
@@ -104,32 +105,33 @@
         mHandlerThread.quitSafely();
     }
 
-    protected ActivityManagerService createActivityManagerService() {
-        final ActivityManagerService service =
-                setupActivityManagerService(new TestActivityManagerService(mContext));
-        AttributeCache.init(mContext);
-        return service;
+    protected ActivityTaskManagerService createActivityTaskManagerService() {
+        final TestActivityTaskManagerService atm = spy(new TestActivityTaskManagerService(mContext));
+        setupActivityManagerService(atm);
+        return atm;
     }
 
-    protected ActivityManagerService setupActivityManagerService(
-            ActivityManagerService service, ActivityTaskManagerService atm) {
-        service = spy(service);
-        // Makes sure activity task is created with the spy object.
-        atm = spy(atm);
-        service.setActivityTaskManager(atm);
-        atm.mAmInternal = service.new LocalService();
+    protected ActivityManagerService createActivityManagerService() {
+        final TestActivityTaskManagerService atm = spy(new TestActivityTaskManagerService(mContext));
+        return setupActivityManagerService(atm);
+    }
+
+    ActivityManagerService setupActivityManagerService(TestActivityTaskManagerService atm) {
+        final ActivityManagerService am = spy(new TestActivityManagerService(mContext, atm));
+        setupActivityManagerService(am, atm);
+        AttributeCache.init(mContext);
+        return am;
+    }
+
+    void setupActivityManagerService(ActivityManagerService am, ActivityTaskManagerService atm) {
+        atm.setActivityManagerService(am);
+        atm.mAmInternal = am.new LocalService();
         // Makes sure the supervisor is using with the spy object.
         atm.mStackSupervisor.setService(atm);
-        doReturn(mock(IPackageManager.class)).when(service).getPackageManager();
-        doNothing().when(service).grantEphemeralAccessLocked(anyInt(), any(), anyInt(), anyInt());
-        service.mWindowManager = prepareMockWindowManager();
-        atm.setWindowManager(service.mWindowManager);
-        return service;
-    }
-
-    protected ActivityManagerService setupActivityManagerService(ActivityManagerService service) {
-        return setupActivityManagerService(
-                service, new TestActivityTaskManagerService(service.mContext));
+        doReturn(mock(IPackageManager.class)).when(am).getPackageManager();
+        doNothing().when(am).grantEphemeralAccessLocked(anyInt(), any(), anyInt(), anyInt());
+        am.mWindowManager = prepareMockWindowManager();
+        atm.setWindowManager(am.mWindowManager);
     }
 
     /**
@@ -141,7 +143,7 @@
 
 
 
-        private final ActivityManagerService mService;
+        private final ActivityTaskManagerService mService;
 
         private ComponentName mComponent;
         private TaskRecord mTaskRecord;
@@ -150,7 +152,7 @@
         private ActivityStack mStack;
         private int mActivityFlags;
 
-        ActivityBuilder(ActivityManagerService service) {
+        ActivityBuilder(ActivityTaskManagerService service) {
             mService = service;
         }
 
@@ -210,8 +212,7 @@
             aInfo.applicationInfo.uid = mUid;
             aInfo.flags |= mActivityFlags;
 
-            final ActivityRecord activity = new ActivityRecord(mService.mActivityTaskManager,
-                    null /* caller */,
+            final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
                     0 /* launchedFromPid */, 0, null, intent, null,
                     aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
                     0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
@@ -222,10 +223,12 @@
                 mTaskRecord.addActivityToTop(activity);
             }
 
-            activity.setProcess(new ProcessRecord(null, null,
-                    mService.mContext.getApplicationInfo(), "name", 12345));
-            activity.app.thread = mock(IApplicationThread.class);
-
+            final WindowProcessController wpc = new WindowProcessController(mService,
+                    mService.mContext.getApplicationInfo(), "name", 12345,
+                    UserHandle.getUserId(12345), mock(Object.class),
+                    mock(WindowProcessListener.class));
+            wpc.setThread(mock(IApplicationThread.class));
+            activity.setProcess(wpc);
             return activity;
         }
     }
@@ -412,8 +415,8 @@
      */
     protected static class TestActivityManagerService extends ActivityManagerService {
 
-        TestActivityManagerService(Context context) {
-            super(context);
+        TestActivityManagerService(Context context, TestActivityTaskManagerService atm) {
+            super(context, atm);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
index aaec238..fbe552d 100644
--- a/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
@@ -57,15 +57,15 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class LaunchParamsControllerTests extends ActivityTestsBase {
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
     private LaunchParamsController mController;
 
     @Before
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mService = createActivityManagerService();
-        mController = new LaunchParamsController(mService.mActivityTaskManager);
+        mService = createActivityTaskManagerService();
+        mController = new LaunchParamsController(mService);
     }
 
     /**
@@ -200,9 +200,9 @@
 
         mController.registerModifier(positioner);
 
-        doNothing().when(mService.mActivityTaskManager).moveStackToDisplay(anyInt(), anyInt());
+        doNothing().when(mService).moveStackToDisplay(anyInt(), anyInt());
         mController.layoutTask(task, null /* windowLayout */);
-        verify(mService.mActivityTaskManager, times(1)).moveStackToDisplay(eq(task.getStackId()),
+        verify(mService, times(1)).moveStackToDisplay(eq(task.getStackId()),
                 eq(params.mPreferredDisplayId));
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 982809a..a4e4409 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -94,7 +94,7 @@
     private static int INVALID_STACK_ID = 999;
 
     private Context mContext = InstrumentationRegistry.getContext();
-    private ActivityTaskManagerService mService;
+    private TestActivityTaskManagerService mService;
     private ActivityDisplay mDisplay;
     private ActivityDisplay mOtherDisplay;
     private ActivityStack mStack;
@@ -145,8 +145,9 @@
         super.setUp();
 
         mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
-        mService = setupActivityManagerService(new MyTestActivityManagerService(mContext),
-                new MyTestActivityTaskManagerService(mContext)).mActivityTaskManager;
+        mService = spy(new MyTestActivityTaskManagerService(mContext));
+        final ActivityManagerService am = spy(new MyTestActivityManagerService(mContext, mService));
+        setupActivityManagerService(am, mService);
         mRecentTasks = (TestRecentTasks) mService.getRecentTasks();
         mRecentTasks.loadParametersFromResources(mContext.getResources());
         mHomeStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
@@ -839,8 +840,8 @@
     }
 
     private class MyTestActivityManagerService extends TestActivityManagerService {
-        MyTestActivityManagerService(Context context) {
-            super(context);
+        MyTestActivityManagerService(Context context, TestActivityTaskManagerService atm) {
+            super(context, atm);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java b/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
index 1f2bca6..b642d26 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
@@ -50,7 +51,7 @@
 public class RecentsAnimationTest extends ActivityTestsBase {
 
     private Context mContext = InstrumentationRegistry.getContext();
-    private ActivityTaskManagerService mService;
+    private TestActivityTaskManagerService mService;
     private ComponentName mRecentsComponent;
 
     @Before
@@ -59,9 +60,8 @@
         super.setUp();
 
         mRecentsComponent = new ComponentName(mContext.getPackageName(), "RecentsActivity");
-        mService = setupActivityManagerService(new TestActivityManagerService(mContext),
-                new MyTestActivityTaskManagerService(mContext)).mActivityTaskManager;
-        AttributeCache.init(mContext);
+        mService = spy(new MyTestActivityTaskManagerService(mContext));
+        setupActivityManagerService(mService);
     }
 
     @Test
@@ -70,14 +70,14 @@
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         ActivityStack recentsStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */);
-        ActivityRecord recentsActivity = new ActivityBuilder(mService.mAm)
+        ActivityRecord recentsActivity = new ActivityBuilder(mService)
                 .setComponent(mRecentsComponent)
                 .setCreateTask(true)
                 .setStack(recentsStack)
                 .build();
         ActivityStack fullscreenStack2 = mService.mStackSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        ActivityRecord fsActivity = new ActivityBuilder(mService.mAm)
+        ActivityRecord fsActivity = new ActivityBuilder(mService)
                 .setComponent(new ComponentName(mContext.getPackageName(), "App1"))
                 .setCreateTask(true)
                 .setStack(fullscreenStack2)
diff --git a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
index c6ce7e1..944f20f 100644
--- a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
@@ -50,7 +50,7 @@
 public class RunningTasksTest extends ActivityTestsBase {
 
     private Context mContext = InstrumentationRegistry.getContext();
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
 
     private RunningTasks mRunningTasks;
 
@@ -59,7 +59,7 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityManagerService();
+        mService = createActivityTaskManagerService();
         mRunningTasks = new RunningTasks();
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
index 3d323f0..f71a6e7 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
@@ -57,7 +57,7 @@
 
     private final static Rect STACK_BOUNDS = new Rect(0, 0, STACK_WIDTH, STACK_HEIGHT);
 
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
     private ActivityStack mStack;
     private TaskRecord mTask;
 
@@ -71,7 +71,7 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityManagerService();
+        mService = createActivityTaskManagerService();
         mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         mStack.requestResize(STACK_BOUNDS);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 3d64f2a..2de5d87 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -41,7 +41,6 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.app.IUidObserver;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.ActivityNotFoundException;
@@ -93,6 +92,7 @@
 import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
 import com.android.server.pm.ShortcutUser.PackageWithUser;
 
+import com.android.server.wm.ActivityTaskManagerInternal;
 import org.junit.Assert;
 import org.mockito.ArgumentCaptor;
 import org.mockito.invocation.InvocationOnMock;
diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index 3514e5a..c4c2ad9 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -14,7 +14,6 @@
 import static org.testng.Assert.assertThrows;
 
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.app.AppOpsManager;
 import android.app.IApplicationThread;
 import android.content.ComponentName;
@@ -32,6 +31,8 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.SparseArray;
 
+import com.android.server.wm.ActivityTaskManagerInternal;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
index 69cfaad..d13c3c9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
@@ -29,7 +29,6 @@
 import static org.mockito.Mockito.mock;
 
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
 import android.content.Context;
 import android.hardware.display.DisplayManagerInternal;
 import android.os.PowerManagerInternal;
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index a919d38..63945a9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -20,8 +20,8 @@
 import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
 
 import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
+
+import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 4e49782..c5d6dc7 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -19,7 +19,7 @@
 import android.Manifest;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.ContentResolver;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 54f99a6..92aa152 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -23,10 +23,9 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 
 import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
-import android.app.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
 import android.content.BroadcastReceiver;
@@ -50,7 +49,6 @@
 import android.util.Slog;
 import android.view.IWindowManager;
 
-import com.android.internal.app.IVoiceInteractionSessionListener;
 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.server.LocalServices;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 606d027..01f5d9c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -16,9 +16,9 @@
 
 package com.android.server.voiceinteraction;
 
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
-import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
+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_STRUCTURE;
 import static android.app.AppOpsManager.OP_ASSIST_SCREENSHOT;
 import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE;
 import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;