Unify Activity level of window hierarchy (50/n).

Make ActivityRecord extend AppWindowToken so we have a single object
for acitvities in the hierarchy.

Bug: 80414790
Test: Existing tests pass.
Change-Id: Ia7f52ef444cba88223f4e8a9586f6c12b1b5e4ea
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index c9e84ec..e54daf2 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -54,20 +54,14 @@
 import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
 import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
-import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
 import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
 import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
-import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
 import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
 import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
 import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
-import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
-import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
-import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
@@ -86,7 +80,6 @@
 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
-import static android.os.Build.VERSION_CODES.HONEYCOMB;
 import static android.os.Build.VERSION_CODES.O;
 import static android.os.Process.SYSTEM_UID;
 import static android.view.Display.DEFAULT_DISPLAY;
@@ -96,6 +89,7 @@
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
 
+import static com.android.server.am.ActivityRecordProto.APP_WINDOW_TOKEN;
 import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
 import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
 import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
@@ -157,6 +151,7 @@
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
 import static com.android.server.wm.TaskPersister.DEBUG;
 import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -211,7 +206,6 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.ArraySet;
@@ -225,16 +219,12 @@
 import android.view.DisplayCutout;
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.IApplicationToken;
-import android.view.RemoteAnimationDefinition;
 import android.view.WindowManager.LayoutParams;
 
-import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.util.XmlUtils;
-import com.android.server.AttributeCache;
-import com.android.server.AttributeCache.Entry;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.am.EventLogTags;
 import com.android.server.am.PendingIntentRecord;
@@ -262,7 +252,7 @@
 /**
  * An entry in the history stack, representing an activity.
  */
-final class ActivityRecord extends ConfigurationContainer {
+final class ActivityRecord extends AppWindowToken {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_APP = TAG + POSTFIX_APP;
@@ -291,29 +281,17 @@
     // How many activities have to be scheduled to stop to force a stop pass.
     private static final int MAX_STOPPING_TO_FORCE = 3;
 
-    final ActivityTaskManagerService mAtmService; // owner
-    final IApplicationToken.Stub appToken; // window manager token
-    // TODO: Remove after unification
-    AppWindowToken mAppWindowToken;
-
+    // TODO: Move to AppWindowToken?
     final ActivityInfo info; // activity info provided by developer in AndroidManifest
     final int launchedFromPid; // always the pid who started the activity.
     final int launchedFromUid; // always the uid who started the activity.
     final String launchedFromPackage; // always the package who started the activity.
-    final int mUserId;          // Which user is this running for?
     final Intent intent;    // the original intent that generated us
-    final ComponentName mActivityComponent;  // the intent component, or target of an alias.
     final String shortComponentName; // the short component name of the intent
     final String resolvedType; // as per original caller;
-    final String packageName; // the package implementing intent's component
     final String processName; // process where this component wants to run
     final String taskAffinity; // as per ActivityInfo.taskAffinity
     final boolean stateNotNeeded; // As per ActivityInfo.flags
-    boolean fullscreen; // The activity is opaque and fills the entire space of this task.
-    // TODO: See if it possible to combine this with the fullscreen field.
-    final boolean hasWallpaper; // Has a wallpaper window as a background.
-    @VisibleForTesting
-    boolean noDisplay;  // activity is not displayed?
     @VisibleForTesting
     int mHandoverLaunchDisplayId = INVALID_DISPLAY; // Handover launch display id to next activity.
     private final boolean componentSpecified;  // did caller specify an explicit component?
@@ -324,7 +302,6 @@
     private int icon;               // resource identifier of activity's icon.
     private int logo;               // resource identifier of activity's logo.
     private int theme;              // resource identifier of activity's theme.
-    private int realTheme;          // actual theme resource we will use, never 0.
     private int windowFlags;        // custom window flags for preview window.
     private TaskRecord task;        // the task this is in.
     private long createTime = System.currentTimeMillis();
@@ -374,6 +351,7 @@
     boolean visible;        // does this activity's window need to be shown?
     boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
                                      // might hide this activity?
+    // TODO: figureout how to consolidate with the same variable in AppWindowToken.
     private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
                                         // process that it is hidden.
     boolean sleeping;       // have we told the activity to sleep?
@@ -393,8 +371,6 @@
     long lastLaunchTime;    // time of last launch of this activity
     ComponentName requestedVrComponent; // the requested component for handling VR mode.
 
-    String stringName;      // for caching of toString().
-
     private boolean inHistory;  // are we in the history stack?
     final ActivityStackSupervisor mStackSupervisor;
     final RootActivityContainer mRootActivityContainer;
@@ -411,8 +387,6 @@
     int mRelaunchReason = RELAUNCH_REASON_NONE;
 
     TaskDescription taskDescription; // the recents information for this activity
-    boolean mLaunchTaskBehind; // this activity is actively being launched with
-        // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.
 
     // These configurations are collected from application's resources based on size-sensitive
     // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
@@ -430,17 +404,6 @@
     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
 
-    // A hint to override the window specified rotation animation, or -1
-    // to use the window specified value. We use this so that
-    // we can select the right animation in the cases of starting
-    // windows, where the app hasn't had time to set a value
-    // on the window.
-    int mRotationAnimationHint = -1;
-
-    private boolean mShowWhenLocked;
-    private boolean mInheritShownWhenLocked;
-    private boolean mTurnScreenOn;
-
     /**
      * Current sequencing integer of the configuration, for skipping old activity configurations.
      */
@@ -603,7 +566,7 @@
                 pw.print(" idle="); pw.print(idle);
                 pw.print(" mStartingWindowState=");
                 pw.println(startingWindowStateToString(mStartingWindowState));
-        pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
+        pw.print(prefix); pw.print("occludesParent="); pw.print(occludesParent());
                 pw.print(" noDisplay="); pw.print(noDisplay);
                 pw.print(" immersive="); pw.print(immersive);
                 pw.print(" launchMode="); pw.println(launchMode);
@@ -855,22 +818,7 @@
         }
     }
 
-    @Override
-    protected int getChildCount() {
-        // {@link ActivityRecord} is a leaf node and has no children.
-        return 0;
-    }
-
-    @Override
-    protected ConfigurationContainer getChildAt(int index) {
-        return null;
-    }
-
-    @Override
-    protected ConfigurationContainer getParent() {
-        return getTaskRecord();
-    }
-
+    // TODO: Remove once TaskRecord and Task are unified.
     TaskRecord getTaskRecord() {
         return task;
     }
@@ -914,31 +862,63 @@
 
         this.task = task;
 
-        if (!reparenting) {
+        // This is attaching the activity to the task which we only want to do once.
+        // TODO: Need to re-work after unifying the task level since it will already have a parent
+        // then. Just need to restructure the re-parent case not to do this. NOTE that the
+        // reparenting flag passed in can't be used directly for this as it isn't set in
+        // ActivityRecord#reparent() case that ends up calling this method.
+        if (task != null && getParent() == null) {
+            inHistory = true;
+            final Task container = task.getTask();
+            if (container != null) {
+                onAttachToTask(task.voiceSession != null, container.getDisplayContent(),
+                        getInputDispatchingTimeoutLocked(this) * 1000000L);
+                ProtoLog.v(WM_DEBUG_ADD_REMOVE, "setTask: %s at top.", this);
+                container.addChild(this, Integer.MAX_VALUE /* add on top */);
+            }
+
+            // TODO(b/36505427): Maybe this call should be moved inside
+            // updateOverrideConfiguration()
+            task.updateOverrideConfigurationFromLaunchBounds();
+            // Make sure override configuration is up-to-date before using to create window
+            // controller.
+            updateOverrideConfiguration();
+
+            task.addActivityToTop(this);
+
+            // When an activity is started directly into a split-screen fullscreen stack, we need to
+            // update the initial multi-window modes so that the callbacks are scheduled correctly
+            // when the user leaves that mode.
+            mLastReportedMultiWindowMode = inMultiWindowMode();
+            mLastReportedPictureInPictureMode = inPinnedWindowingMode();
+        } else if (!reparenting) {
             onParentChanged();
         }
     }
 
     /**
-     * Notifies AWT that this app is waiting to pause in order to determine if it will enter PIP.
-     * This information helps AWT know that the app is in the process of pausing before it gets the
-     * signal on the WM side.
+     * Sets the Task on this activity for the purposes of re-use during launch where we will
+     * re-use another activity instead of this one for the launch.
      */
-    void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
-        if (mAppWindowToken == null) {
-            return;
-        }
-
-        mAppWindowToken.setWillCloseOrEnterPip(willCloseOrEnterPip);
+    void setTaskForReuse(TaskRecord task) {
+        this.task = task;
     }
 
     static class Token extends IApplicationToken.Stub {
-        private final WeakReference<ActivityRecord> weakActivity;
+        private WeakReference<ActivityRecord> weakActivity;
         private final String name;
+        private final String tokenString;
 
-        Token(ActivityRecord activity, Intent intent) {
-            weakActivity = new WeakReference<>(activity);
+        Token(Intent intent) {
             name = intent.getComponent().flattenToShortString();
+            tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
+        }
+
+        private void attach(ActivityRecord activity) {
+            if (weakActivity != null) {
+                throw new IllegalStateException("Already attached..." + this);
+            }
+            weakActivity = new WeakReference<>(activity);
         }
 
         private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
@@ -958,7 +938,9 @@
             sb.append("Token{");
             sb.append(Integer.toHexString(System.identityHashCode(this)));
             sb.append(' ');
-            sb.append(weakActivity.get());
+            if (weakActivity != null) {
+                sb.append(weakActivity.get());
+            }
             sb.append('}');
             return sb.toString();
         }
@@ -1005,14 +987,15 @@
             ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
             boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
             ActivityOptions options, ActivityRecord sourceRecord) {
-        mAtmService = _service;
+        super(_service.mWindowManager, _service, new Token(_intent), aInfo, options, _intent,
+                null /* displayContent */);
+        appToken.attach(this);
+
         mRootActivityContainer = _service.mRootActivityContainer;
-        appToken = new Token(this, _intent);
         info = aInfo;
         launchedFromPid = _launchedFromPid;
         launchedFromUid = _launchedFromUid;
         launchedFromPackage = _launchedFromPackage;
-        mUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
         intent = _intent;
         shortComponentName = _intent.getComponent().flattenToShortString();
         resolvedType = _resolvedType;
@@ -1037,17 +1020,6 @@
         hasBeenLaunched = false;
         mStackSupervisor = supervisor;
 
-        // If the class name in the intent doesn't match that of the target, this is
-        // probably an alias. We have to create a new ComponentName object to keep track
-        // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
-        if (aInfo.targetActivity == null
-                || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
-                && (aInfo.launchMode == LAUNCH_MULTIPLE
-                || aInfo.launchMode == LAUNCH_SINGLE_TOP))) {
-            mActivityComponent = _intent.getComponent();
-        } else {
-            mActivityComponent = new ComponentName(aInfo.packageName, aInfo.targetActivity);
-        }
         taskAffinity = aInfo.taskAffinity;
         stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
         nonLocalizedLabel = aInfo.nonLocalizedLabel;
@@ -1060,11 +1032,6 @@
         icon = aInfo.getIconResource();
         logo = aInfo.getLogoResource();
         theme = aInfo.getThemeResource();
-        realTheme = theme;
-        if (realTheme == 0) {
-            realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
-                    ? android.R.style.Theme : android.R.style.Theme_Holo;
-        }
         if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
             windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
@@ -1080,21 +1047,8 @@
             intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
         }
 
-        packageName = aInfo.applicationInfo.packageName;
         launchMode = aInfo.launchMode;
 
-        Entry ent = AttributeCache.instance().get(packageName,
-                realTheme, com.android.internal.R.styleable.Window, mUserId);
-
-        if (ent != null) {
-            fullscreen = !ActivityInfo.isTranslucentOrFloating(ent.array);
-            hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
-            noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
-        } else {
-            hasWallpaper = false;
-            noDisplay = false;
-        }
-
         setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
 
         immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
@@ -1102,11 +1056,6 @@
         requestedVrComponent = (aInfo.requestedVrComponent == null) ?
                 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
 
-        mShowWhenLocked = (aInfo.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
-        mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
-        mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
-
-        mRotationAnimationHint = aInfo.rotationAnimation;
         lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
         if (info.applicationInfo.isPrivilegedApp()
                 && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
@@ -1116,13 +1065,6 @@
 
         if (options != null) {
             pendingOptions = options;
-            mLaunchTaskBehind = options.getLaunchTaskBehind();
-
-            final int rotationAnimation = pendingOptions.getRotationAnimationHint();
-            // Only override manifest supplied option if set.
-            if (rotationAnimation >= 0) {
-                mRotationAnimationHint = rotationAnimation;
-            }
             final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
             if (usageReport != null) {
                 appTimeTracker = new AppTimeTracker(usageReport);
@@ -1152,53 +1094,6 @@
         return hasProcess() && app.hasThread();
     }
 
-    void createAppWindowToken() {
-        if (mAppWindowToken != null) {
-            throw new IllegalArgumentException("App Window Token=" + mAppWindowToken
-                    + " already created for r=" + this);
-        }
-
-        inHistory = true;
-
-        // TODO(b/36505427): Maybe this call should be moved inside updateOverrideConfiguration()
-        task.updateOverrideConfigurationFromLaunchBounds();
-        // Make sure override configuration is up-to-date before using to create window controller.
-        updateOverrideConfiguration();
-
-        // TODO: remove after unification
-        mAppWindowToken = mAtmService.mWindowManager.mRoot.getAppWindowToken(appToken.asBinder());
-        if (mAppWindowToken != null) {
-            // TODO: Should this throw an exception instead?
-            Slog.w(TAG, "Attempted to add existing app token: " + appToken);
-        } else {
-            final Task container = task.getTask();
-            if (container == null) {
-                throw new IllegalArgumentException("createAppWindowToken: invalid task =" + task);
-            }
-            mAppWindowToken = createAppWindow(mAtmService.mWindowManager, appToken,
-                    task.voiceSession != null, container.getDisplayContent(),
-                    ActivityTaskManagerService.getInputDispatchingTimeoutLocked(this)
-                            * 1000000L, fullscreen,
-                    (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0,
-                    info.applicationInfo.targetSdkVersion,
-                    info.screenOrientation, mRotationAnimationHint,
-                    mLaunchTaskBehind, isAlwaysFocusable());
-            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addAppToken: %s"
-                            + " task=%s at %d", mAppWindowToken, container,
-                    Integer.MAX_VALUE);
-
-            container.addChild(mAppWindowToken, Integer.MAX_VALUE /* add on top */);
-        }
-
-        task.addActivityToTop(this);
-
-        // When an activity is started directly into a split-screen fullscreen stack, we need to
-        // update the initial multi-window modes so that the callbacks are scheduled correctly when
-        // the user leaves that mode.
-        mLastReportedMultiWindowMode = inMultiWindowMode();
-        mLastReportedPictureInPictureMode = inPinnedWindowingMode();
-    }
-
     boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
             IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
@@ -1207,40 +1102,20 @@
                     + " pkg=%s transferFrom=%s newTask=%b taskSwitch=%b processRunning=%b"
                     + " allowTaskSnapshot=%b", appToken, pkg, transferFrom, newTask, taskSwitch,
                 processRunning, allowTaskSnapshot);
-
-        if (mAppWindowToken == null) {
-            Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + appToken);
-            return false;
-        }
-        if (mAppWindowToken.getTask() == null) {
-            // Can be removed after unification of Task and TaskRecord.
+        if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to start a window to an app token not having attached to any"
                     + " task: " + appToken);
             return false;
         }
-        return mAppWindowToken.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
+        return super.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
                 labelRes, icon, logo, windowFlags, transferFrom, newTask, taskSwitch,
                 processRunning, allowTaskSnapshot, activityCreated, fromRecents);
     }
 
-    // TODO: Remove after unification
-    @VisibleForTesting
-    AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
-            boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
-            boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
-            int rotationAnimationHint, boolean launchTaskBehind,
-            boolean alwaysFocusable) {
-        return new AppWindowToken(service, token, mActivityComponent, voiceInteraction, dc,
-                inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
-                rotationAnimationHint, launchTaskBehind, alwaysFocusable,
-                this);
-    }
-
     void removeWindowContainer() {
-        if (mAtmService.mWindowManager.mRoot == null) return;
+        if (mWmService.mRoot == null) return;
 
-        final DisplayContent dc = mAtmService.mWindowManager.mRoot.getDisplayContent(
-                getDisplayId());
+        final DisplayContent dc = mWmService.mRoot.getDisplayContent(getDisplayId());
         if (dc == null) {
             Slog.w(TAG, "removeWindowContainer: Attempted to remove token: "
                     + appToken + " from non-existing displayId=" + getDisplayId());
@@ -1256,7 +1131,7 @@
      * should ensure that the {@param newTask} is not already the parent of this activity.
      */
     void reparent(TaskRecord newTask, int position, String reason) {
-        if (mAppWindowToken == null) {
+        if (getParent() == null) {
             Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
             return;
         }
@@ -1275,7 +1150,7 @@
                     + " r=" + this + " (" + prevTask.getStackId() + ")");
         }
 
-        mAppWindowToken.reparent(newTask.getTask(), position);
+        reparent(newTask.getTask(), position);
 
         // Reparenting prevents informing the parent stack of activity removal in the case that
         // the new stack has the same parent. we must manually signal here if this is not the case.
@@ -1366,6 +1241,7 @@
     /**
      * @return Stack value from current task, null if there is no task.
      */
+    // TODO: Remove once ActivityStack and TaskStack are unified.
     <T extends ActivityStack> T getActivityStack() {
         return task != null ? (T) task.getStack() : null;
     }
@@ -1380,14 +1256,13 @@
     }
 
     boolean setOccludesParent(boolean occludesParent) {
-        final boolean changed = mAppWindowToken.setOccludesParent(occludesParent);
+        final boolean changed = super.setOccludesParent(occludesParent);
         if (changed) {
             if (!occludesParent) {
                 getActivityStack().convertActivityToTranslucent(this);
             }
             // Keep track of the number of fullscreen activities in this task.
             task.numFullscreen += occludesParent ? +1 : -1;
-            fullscreen = occludesParent;
         }
         // Always ensure visibility if this activity doesn't occlude parent, so the
         // {@link #returningOptions} of the activity under this one can be applied in
@@ -1556,10 +1431,6 @@
                 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
     }
 
-    boolean isAlwaysFocusable() {
-        return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
-    }
-
     /** Move activity with its stack to front and make the stack focused. */
     boolean moveFocusableActivityToTop(String reason) {
         if (!isFocusable()) {
@@ -2200,9 +2071,7 @@
         stack.removeTimeoutsForActivity(this);
         // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
         // manager so it can update its bookkeeping.
-        if (mAppWindowToken != null) {
-            mAppWindowToken.clearRelaunching();
-        }
+        clearRelaunching();
     }
 
     /**
@@ -2368,7 +2237,7 @@
      */
     void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
         final int animationType = pendingOptions.getAnimationType();
-        final DisplayContent displayContent = mAppWindowToken.getDisplayContent();
+        final DisplayContent displayContent = getDisplayContent();
         switch (animationType) {
             case ANIM_CUSTOM:
                 displayContent.mAppTransition.overridePendingAppTransition(
@@ -2502,11 +2371,8 @@
         if (!keysPaused) {
             keysPaused = true;
 
-            // TODO: remove the check after unification with AppWindowToken. The DC check is not
-            // needed after no mock mAppWindowToken in tests.
-            if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
-                mAppWindowToken.getDisplayContent().getInputMonitor().pauseDispatchingLw(
-                        mAppWindowToken);
+            if (getDisplayContent() != null) {
+                getDisplayContent().getInputMonitor().pauseDispatchingLw(this);
             }
         }
     }
@@ -2515,11 +2381,8 @@
         if (keysPaused) {
             keysPaused = false;
 
-            // TODO: remove the check after unification with AppWindowToken. The DC check is not
-            // needed after no mock mAppWindowToken in tests.
-            if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
-                mAppWindowToken.getDisplayContent().getInputMonitor().resumeDispatchingLw(
-                        mAppWindowToken);
+            if (getDisplayContent() != null) {
+                getDisplayContent().getInputMonitor().resumeDispatchingLw(this);
             }
         }
     }
@@ -2541,12 +2404,12 @@
     }
 
     void setVisibility(boolean visible) {
-        if (mAppWindowToken == null) {
+        if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
                     + appToken);
             return;
         }
-        mAppWindowToken.setVisibility(visible, mDeferHidingClient);
+        setVisibility(visible, mDeferHidingClient);
         mAtmService.addWindowLayoutReasons(
                 ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
         mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
@@ -2582,12 +2445,12 @@
         // an indication that the Surface will eventually be destroyed.
         // This however isn't necessarily true if we are going to sleep.
         if (state == STOPPING && !isSleeping()) {
-            if (mAppWindowToken == null) {
+            if (getParent() == null) {
                 Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
                         + appToken);
                 return;
             }
-            mAppWindowToken.detachChildren();
+            detachChildren();
         }
 
         if (state == RESUMED) {
@@ -2646,23 +2509,20 @@
     }
 
     void notifyAppResumed(boolean wasStopped) {
-        if (mAppWindowToken == null) {
+        if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
                     + appToken);
             return;
         }
-        mAppWindowToken.notifyAppResumed(wasStopped);
+        super.notifyAppResumed(wasStopped);
     }
 
     void notifyUnknownVisibilityLaunched() {
 
         // No display activities never add a window, so there is no point in waiting them for
         // relayout.
-        if (!noDisplay) {
-            if (mAppWindowToken != null) {
-                mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
-                        .notifyLaunched(mAppWindowToken);
-            }
+        if (!noDisplay && getDisplayContent() != null) {
+            getDisplayContent().mUnknownAppVisibilityController.notifyLaunched(this);
         }
     }
 
@@ -2962,10 +2822,7 @@
             display.handleActivitySizeCompatModeIfNeeded(r);
         }
 
-        if (r.mAppWindowToken != null) {
-            r.mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
-                    .notifyAppResumedFinished(r.mAppWindowToken);
-        }
+        r.getDisplayContent().mUnknownAppVisibilityController.notifyAppResumedFinished(r);
     }
 
     /**
@@ -3113,9 +2970,7 @@
                 setState(STOPPED, "activityStoppedLocked");
             }
 
-            if (mAppWindowToken != null) {
-                mAppWindowToken.notifyAppStopped();
-            }
+            notifyAppStopped();
 
             if (finishing) {
                 clearOptionsLocked();
@@ -3192,9 +3047,11 @@
         stack.removeLaunchTickMessages();
     }
 
-    // IApplicationToken
+    boolean mayFreezeScreenLocked() {
+        return mayFreezeScreenLocked(app);
+    }
 
-    public boolean mayFreezeScreenLocked(WindowProcessController app) {
+    private 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,
@@ -3202,9 +3059,13 @@
         return hasProcess() && !app.isCrashing() && !app.isNotResponding();
     }
 
-    public void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
+    void startFreezingScreenLocked(int configChanges) {
+        startFreezingScreenLocked(app, configChanges);
+    }
+
+    void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
         if (mayFreezeScreenLocked(app)) {
-            if (mAppWindowToken == null) {
+            if (getParent() == null) {
                 Slog.w(TAG_WM,
                         "Attempted to freeze screen with non-existing app token: " + appToken);
                 return;
@@ -3212,29 +3073,29 @@
 
             // Window configuration changes only effect windows, so don't require a screen freeze.
             int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
-            if (freezableConfigChanges == 0 && mAppWindowToken.okToDisplay()) {
+            if (freezableConfigChanges == 0 && okToDisplay()) {
                 ProtoLog.v(WM_DEBUG_ORIENTATION, "Skipping set freeze of %s", appToken);
                 return;
             }
 
-            mAppWindowToken.startFreezingScreen();
+            startFreezingScreen();
         }
     }
 
-    public void stopFreezingScreenLocked(boolean force) {
+    void stopFreezingScreenLocked(boolean force) {
         if (force || frozenBeforeDestroy) {
             frozenBeforeDestroy = false;
-            if (mAppWindowToken == null) {
+            if (getParent() == null) {
                 return;
             }
             ProtoLog.v(WM_DEBUG_ORIENTATION,
                         "Clear freezing of %s: hidden=%b freezing=%b", appToken,
-                                mAppWindowToken.isHidden(), mAppWindowToken.isFreezingScreen());
-            mAppWindowToken.stopFreezingScreen(true, force);
+                                isHidden(), isFreezingScreen());
+            stopFreezingScreen(true, force);
         }
     }
 
-    public void reportFullyDrawnLocked(boolean restoredFromBundle) {
+    void reportFullyDrawnLocked(boolean restoredFromBundle) {
         final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
                 .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
         if (info != null) {
@@ -3243,74 +3104,42 @@
         }
     }
 
-    /**
-     * Called when the starting window for this container is drawn.
-     */
-    public void onStartingWindowDrawn(long timestamp) {
-        synchronized (mAtmService.mGlobalLock) {
-            mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
-                    getWindowingMode(), timestamp);
-        }
-    }
-
     /** Called when the windows associated app window container are drawn. */
-    public void onWindowsDrawn(boolean drawn, long timestamp) {
-        synchronized (mAtmService.mGlobalLock) {
-            mDrawn = drawn;
-            if (!drawn) {
-                return;
-            }
-            final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
-                    .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
-            final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
-            final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
-            mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
-                    windowsDrawnDelayMs, launchState);
-            mStackSupervisor.stopWaitingForActivityVisible(this);
-            finishLaunchTickingLocked();
-            if (task != null) {
-                task.hasBeenVisible = true;
-            }
+    void onWindowsDrawn(boolean drawn, long timestamp) {
+        mDrawn = drawn;
+        if (!drawn) {
+            return;
+        }
+        final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
+                .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
+        final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
+        final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
+        mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
+                windowsDrawnDelayMs, launchState);
+        mStackSupervisor.stopWaitingForActivityVisible(this);
+        finishLaunchTickingLocked();
+        if (task != null) {
+            task.hasBeenVisible = true;
         }
     }
 
     /** Called when the windows associated app window container are visible. */
-    public void onWindowsVisible() {
-        synchronized (mAtmService.mGlobalLock) {
-            mStackSupervisor.stopWaitingForActivityVisible(this);
-            if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
-            if (!nowVisible) {
-                nowVisible = true;
-                lastVisibleTime = SystemClock.uptimeMillis();
-                mAtmService.scheduleAppGcsLocked();
-            }
+    void onWindowsVisible() {
+        super.onWindowsVisible();
+        mStackSupervisor.stopWaitingForActivityVisible(this);
+        if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
+        if (!nowVisible) {
+            nowVisible = true;
+            lastVisibleTime = SystemClock.uptimeMillis();
+            mAtmService.scheduleAppGcsLocked();
         }
     }
 
     /** Called when the windows associated app window container are no longer visible. */
-    public void onWindowsGone() {
-        synchronized (mAtmService.mGlobalLock) {
-            if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
-            nowVisible = false;
-        }
-    }
-
-    void onAnimationFinished() {
-        if (mRootActivityContainer.allResumedActivitiesIdle()
-                || mStackSupervisor.isStoppingNoHistoryActivity()) {
-            // If all activities are already idle or there is an activity that must be
-            // stopped immediately after visible, then we now need to make sure we perform
-            // the full stop of this activity. This is because we won't do that while they are still
-            // waiting for the animation to finish.
-            if (mStackSupervisor.mStoppingActivities.contains(this)) {
-                mStackSupervisor.scheduleIdleLocked();
-            }
-        } else {
-            // Instead of doing the full stop routine here, let's just hide any activities
-            // we now can, and let them stop when the normal idle happens.
-            mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
-                    false /* remove */, true /* processPausingActivities */);
-        }
+    void onWindowsGone() {
+        super.onWindowsGone();
+        if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
+        nowVisible = false;
     }
 
     /**
@@ -3496,9 +3325,6 @@
 
     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
             boolean fromRecents) {
-        if (mAppWindowToken == null) {
-            return;
-        }
         if (mTaskOverlay) {
             // We don't show starting window for overlay activities.
             return;
@@ -3526,26 +3352,20 @@
         if (mStartingWindowState == STARTING_WINDOW_SHOWN && behindFullscreenActivity) {
             if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
             mStartingWindowState = STARTING_WINDOW_REMOVED;
-            mAppWindowToken.removeStartingWindow();
+            removeStartingWindow();
         }
     }
 
     void setRequestedOrientation(int requestedOrientation) {
-        setOrientation(requestedOrientation, mayFreezeScreenLocked(app));
+        setOrientation(requestedOrientation, mayFreezeScreenLocked());
         mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
                 task.taskId, requestedOrientation);
     }
 
     private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
-        if (mAppWindowToken == null) {
-            Slog.w(TAG_WM,
-                    "Attempted to set orientation of non-existing app token: " + appToken);
-            return;
-        }
-
         final IBinder binder =
                 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
-        mAppWindowToken.setOrientation(requestedOrientation, binder, this);
+        setOrientation(requestedOrientation, binder, this);
 
         // Push the new configuration to the requested app in case where it's not pushed, e.g. when
         // the request is handled at task level with letterbox.
@@ -3555,23 +3375,6 @@
         }
     }
 
-    int getOrientation() {
-        if (mAppWindowToken == null) {
-            return info.screenOrientation;
-        }
-
-        return mAppWindowToken.getOrientationIgnoreVisibility();
-    }
-
-    void setDisablePreviewScreenshots(boolean disable) {
-        if (mAppWindowToken == null) {
-            Slog.w(TAG_WM, "Attempted to set disable screenshots of non-existing app"
-                    + " token: " + appToken);
-            return;
-        }
-        mAppWindowToken.setDisablePreviewScreenshots(disable);
-    }
-
     /**
      * Set the last reported global configuration to the client. Should be called whenever a new
      * global configuration is sent to the client for this activity.
@@ -3594,33 +3397,6 @@
     }
 
     /**
-     * Get the configuration orientation by the requested screen orientation
-     * ({@link ActivityInfo.ScreenOrientation}) of this activity.
-     *
-     * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
-     *         {@link Configuration#ORIENTATION_PORTRAIT},
-     *         {@link Configuration#ORIENTATION_UNDEFINED}).
-     */
-    int getRequestedConfigurationOrientation() {
-        final int screenOrientation = getOrientation();
-        if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
-            // NOSENSOR means the display's "natural" orientation, so return that.
-            final ActivityDisplay display = getDisplay();
-            if (display != null && display.mDisplayContent != null) {
-                return display.mDisplayContent.getNaturalOrientation();
-            }
-        } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
-            // LOCKED means the activity's orientation remains unchanged, so return existing value.
-            return getConfiguration().orientation;
-        } else if (isFixedOrientationLandscape(screenOrientation)) {
-            return ORIENTATION_LANDSCAPE;
-        } else if (isFixedOrientationPortrait(screenOrientation)) {
-            return ORIENTATION_PORTRAIT;
-        }
-        return ORIENTATION_UNDEFINED;
-    }
-
-    /**
      * @return {@code true} if this activity is in size compatibility mode that uses the different
      *         density or bounds from its parent.
      */
@@ -3701,6 +3477,8 @@
     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
     private void updateOverrideConfiguration() {
         final Configuration overrideConfig = mTmpConfig;
+        overrideConfig.setTo(getRequestedOverrideConfiguration());
+
         if (shouldUseSizeCompatMode()) {
             if (mCompatDisplayInsets != null) {
                 // The override configuration is set only once in size compatibility mode.
@@ -3719,7 +3497,6 @@
             // are relative to bounds and density, they will be calculated in
             // {@link TaskRecord#computeConfigResourceOverrides} and the result will also be
             // relatively fixed.
-            overrideConfig.unset();
             overrideConfig.colorMode = parentConfig.colorMode;
             overrideConfig.densityDpi = parentConfig.densityDpi;
             overrideConfig.screenLayout = parentConfig.screenLayout
@@ -3746,7 +3523,6 @@
                 return;
             }
 
-            overrideConfig.unset();
             overrideConfig.windowConfiguration.setBounds(mTmpBounds);
         }
 
@@ -3873,22 +3649,6 @@
             onMergedOverrideConfigurationChanged();
         }
 
-        // TODO(b/80414790): Remove code below after unification.
-        // Same as above it doesn't notify configuration listeners, and consequently AppWindowToken
-        // can't get updated seq number. However WindowState's merged override configuration needs
-        // to have this seq number because that's also used for activity config pushes during layout
-        // traversal. Therefore explicitly update them here.
-        if (mAppWindowToken == null) {
-            return;
-        }
-        final Configuration appWindowTokenRequestedOverrideConfig =
-                mAppWindowToken.getRequestedOverrideConfiguration();
-        if (appWindowTokenRequestedOverrideConfig.seq != getResolvedOverrideConfiguration().seq) {
-            appWindowTokenRequestedOverrideConfig.seq =
-                    getResolvedOverrideConfiguration().seq;
-            mAppWindowToken.onMergedOverrideConfigurationChanged();
-        }
-
         final ActivityDisplay display = getDisplay();
         if (display == null) {
             return;
@@ -3916,7 +3676,7 @@
 
     /** Returns true if the configuration is compatible with this activity. */
     boolean isConfigurationCompatible(Configuration config) {
-        final int orientation = getOrientation();
+        final int orientation = getRequestedOrientation();
         if (isFixedOrientationPortrait(orientation)
                 && config.orientation != ORIENTATION_PORTRAIT) {
             return false;
@@ -4149,7 +3909,7 @@
         if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
             // Aha, the activity isn't handling the change, so DIE DIE DIE.
             configChangeFlags |= changes;
-            startFreezingScreenLocked(app, globalChanges);
+            startFreezingScreenLocked(globalChanges);
             forceNewConfig = false;
             preserveWindow &= isResizeOnlyChange(changes);
             final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
@@ -4307,16 +4067,14 @@
                         : AM_RELAUNCH_ACTIVITY, mUserId, System.identityHashCode(this),
                 task.taskId, shortComponentName);
 
-        startFreezingScreenLocked(app, 0);
+        startFreezingScreenLocked(0);
 
         try {
             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
                     "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
                             + " callers=" + Debug.getCallers(6));
             forceNewConfig = false;
-            if (mAppWindowToken != null) {
-                mAppWindowToken.startRelaunching();
-            }
+            startRelaunching();
             final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
                     pendingNewIntents, configChangeFlags,
                     new MergedConfiguration(mAtmService.getGlobalConfiguration(),
@@ -4405,8 +4163,8 @@
             return;
         }
 
-        if (mAppWindowToken != null) {
-            mAppWindowToken.startFreezingScreen();
+        if (getParent() != null) {
+            startFreezingScreen();
         }
         // The process will be killed until the activity reports stopped with saved state (see
         // {@link ActivityTaskManagerService.activityStopped}).
@@ -4574,67 +4332,24 @@
         return info.applicationInfo.uid;
     }
 
-    void setShowWhenLocked(boolean showWhenLocked) {
-        mShowWhenLocked = showWhenLocked;
-        mRootActivityContainer.ensureActivitiesVisible(null, 0 /* configChanges */,
-                false /* preserveWindows */);
-    }
-
-    void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
-        mInheritShownWhenLocked = inheritShowWhenLocked;
-        mRootActivityContainer.ensureActivitiesVisible(null, 0, false);
-    }
-
-    /**
-     * @return true if the activity windowing mode is not
-     *         {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
-     *         contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
-     *         activity has set {@link #mShowWhenLocked}, or b) if the activity has set
-     *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
-     *         conditions a) above.
-     *         Multi-windowing mode will be exited if true is returned.
-     */
-    boolean canShowWhenLocked() {
-        if (!inPinnedWindowingMode() && (mShowWhenLocked
-                || (mAppWindowToken != null && mAppWindowToken.containsShowWhenLockedWindow()))) {
-            return true;
-        } else if (mInheritShownWhenLocked) {
-            ActivityRecord r = getActivityBelow();
-            return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
-                    || (r.mAppWindowToken != null
-                        && r.mAppWindowToken.containsShowWhenLockedWindow()));
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
-     * such activity exists.
-     */
-    @Nullable
-    private ActivityRecord getActivityBelow() {
-        final int pos = task.mActivities.indexOf(this);
-        if (pos == -1) {
-            throw new IllegalStateException("Activity not found in its task");
-        }
-        return pos == 0 ? null : task.getChildAt(pos - 1);
-    }
-
-    void setTurnScreenOn(boolean turnScreenOn) {
-        mTurnScreenOn = turnScreenOn;
+    @Override
+    int getPid() {
+        return app != null ? app.getPid() : 0;
     }
 
     /**
      * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
-     * {@link #mTurnScreenOn} is set and checks whether the ActivityRecord should be visible
-     * depending on Keyguard state
+     * {@link AppWindowToken#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
+     * should be visible depending on Keyguard state
      *
      * @return true if the screen can be turned on, false otherwise.
      */
     boolean canTurnScreenOn() {
+        if (!getTurnScreenOnFlag()) {
+            return false;
+        }
         final ActivityStack stack = getActivityStack();
-        return mTurnScreenOn && stack != null &&
+        return stack != null &&
                 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
     }
 
@@ -4648,10 +4363,6 @@
         return app == null || app.updateTopResumingActivityInProcessIfNeeded(this);
     }
 
-    boolean getTurnScreenOnFlag() {
-        return mTurnScreenOn;
-    }
-
     boolean isTopRunningActivity() {
         return mRootActivityContainer.topRunningActivity() == this;
     }
@@ -4686,20 +4397,11 @@
         return task.getChildAt(0) == this;
     }
 
-    void registerRemoteAnimations(RemoteAnimationDefinition definition) {
-        if (mAppWindowToken == null) {
-            Slog.w(TAG_WM, "Attempted to register remote animations with non-existing app"
-                    + " token: " + appToken);
-            return;
-        }
-        mAppWindowToken.registerRemoteAnimations(definition);
-    }
-
     @Override
     public String toString() {
         if (stringName != null) {
             return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) +
-                    (finishing ? " f}" : "}");
+                    (finishing ? " f}" : "") + (mIsExiting ? " mIsExiting=" : "") + "}";
         }
         StringBuilder sb = new StringBuilder(128);
         sb.append("ActivityRecord{");
@@ -4709,15 +4411,7 @@
         sb.append(' ');
         sb.append(intent.getComponent().flattenToShortString());
         stringName = sb.toString();
-        return toString();
-    }
-
-    void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
-        final long token = proto.start(fieldId);
-        proto.write(HASH_CODE, System.identityHashCode(this));
-        proto.write(USER_ID, mUserId);
-        proto.write(TITLE, intent.getComponent().flattenToShortString());
-        proto.end(token);
+        return stringName;
     }
 
     /**
@@ -4725,7 +4419,7 @@
      * {@code ActivityRecordProto} is the outer-most proto data.
      */
     void writeToProto(ProtoOutputStream proto) {
-        super.writeToProto(proto, CONFIGURATION_CONTAINER, WindowTraceLogLevel.ALL);
+        super.writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
         writeIdentifierToProto(proto, IDENTIFIER);
         proto.write(STATE, mState.toString());
         proto.write(VISIBLE, visible);
@@ -4733,7 +4427,7 @@
         if (hasProcess()) {
             proto.write(PROC_ID, app.getPid());
         }
-        proto.write(TRANSLUCENT, !fullscreen);
+        proto.write(TRANSLUCENT, !occludesParent());
     }
 
     public void writeToProto(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index ab1f258..24f58f1 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1896,7 +1896,7 @@
                     continue;
                 }
 
-                if (r.fullscreen || r.hasWallpaper) {
+                if (r.occludesParent() || r.hasWallpaper) {
                     // Stack isn't translucent if it has at least one fullscreen activity
                     // that is visible.
                     return false;
@@ -2259,8 +2259,7 @@
                 .isKeyguardOrAodShowing(displayId);
         final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked();
         final boolean showWhenLocked = r.canShowWhenLocked();
-        final boolean dismissKeyguard = r.mAppWindowToken != null
-                && r.mAppWindowToken.containsDismissKeyguardWindow();
+        final boolean dismissKeyguard = r.containsDismissKeyguardWindow();
         if (shouldBeVisible) {
             if (dismissKeyguard && mTopDismissingKeyguardActivity == null) {
                 mTopDismissingKeyguardActivity = r;
@@ -2329,7 +2328,7 @@
             // get it started and resume if no other stack in this stack is resumed.
             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
             if (r != starting) {
-                r.startFreezingScreenLocked(r.app, configChanges);
+                r.startFreezingScreenLocked(configChanges);
             }
             if (!r.visible || r.mLaunchTaskBehind) {
                 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
@@ -2345,7 +2344,7 @@
 
     private boolean updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity,
             ActivityRecord r) {
-        if (r.fullscreen) {
+        if (r.occludesParent()) {
             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
                         + " stackInvisible=" + stackInvisible
                         + " behindFullscreenActivity=" + behindFullscreenActivity);
@@ -2431,12 +2430,12 @@
                     if (r == topActivity) {
                         aboveTop = false;
                     }
-                    behindFullscreenActivity |= r.fullscreen;
+                    behindFullscreenActivity |= r.occludesParent();
                     continue;
                 }
 
                 r.removeOrphanedStartingWindow(behindFullscreenActivity);
-                behindFullscreenActivity |= r.fullscreen;
+                behindFullscreenActivity |= r.occludesParent();
             }
         }
     }
@@ -2566,8 +2565,7 @@
                 final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard
                         && next.canShowWhenLocked();
                 final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next
-                        && next.mAppWindowToken != null
-                        && next.mAppWindowToken.containsDismissKeyguardWindow();
+                        && next.containsDismissKeyguardWindow();
 
                 if (canShowWhenLocked || mayDismissKeyguard) {
                     ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
@@ -2776,7 +2774,7 @@
             final boolean lastActivityTranslucent = lastFocusedStack != null
                     && (lastFocusedStack.inMultiWindowMode()
                     || (lastFocusedStack.mLastPausedActivity != null
-                    && !lastFocusedStack.mLastPausedActivity.fullscreen));
+                    && !lastFocusedStack.mLastPausedActivity.occludesParent()));
 
             // This activity is now becoming visible.
             if (!next.visible || next.stopped || lastActivityTranslucent) {
@@ -3055,7 +3053,7 @@
                     if (!startIt) {
                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
                                 + task, new RuntimeException("here").fillInStackTrace());
-                        r.createAppWindowToken();
+                        r.setTask(rTask);
                         ActivityOptions.abort(options);
                         return;
                     }
@@ -3082,12 +3080,7 @@
         // Slot the activity into the history stack and proceed
         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
                 new RuntimeException("here").fillInStackTrace());
-        // TODO: Need to investigate if it is okay for the controller to already be created by the
-        // time we get to this point. I think it is, but need to double check.
-        // Use test in b/34179495 to trace the call path.
-        if (r.mAppWindowToken == null) {
-            r.createAppWindowToken();
-        }
+        r.setTask(task);
 
         // The transition animation and starting window are not needed if {@code allowMoveToFront}
         // is false, because the activity won't be visible.
@@ -3944,7 +3937,7 @@
                 if (r.finishing) {
                     continue;
                 }
-                if (r.fullscreen) {
+                if (r.occludesParent()) {
                     lastIsOpaque = true;
                 }
                 if (owner != null && r.app != owner) {
@@ -4335,7 +4328,7 @@
                 final ActivityRecord r = activities.get(activityIndex);
                 updatedConfig |= r.ensureActivityConfiguration(0 /* globalChanges */,
                         preserveWindow);
-                if (r.fullscreen) {
+                if (r.occludesParent()) {
                     behindFullscreen = true;
                     break;
                 }
@@ -4438,7 +4431,7 @@
                 if (r.appToken == token) {
                     return true;
                 }
-                if (r.fullscreen && !r.finishing) {
+                if (r.occludesParent() && !r.finishing) {
                     return false;
                 }
             }
@@ -4718,8 +4711,7 @@
                 if (a.info.packageName.equals(packageName)) {
                     a.forceNewConfig = true;
                     if (starting != null && a == starting && a.visible) {
-                        a.startFreezingScreenLocked(starting.app,
-                                CONFIG_SCREEN_LAYOUT);
+                        a.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
                     }
                 }
             }
@@ -4950,7 +4942,7 @@
             if (top != null && !top.isConfigurationCompatible(parentConfig)) {
                 // The final orientation of this activity will change after moving to full screen.
                 // Start freezing screen here to prevent showing a temporary full screen window.
-                top.startFreezingScreenLocked(top.app, CONFIG_SCREEN_LAYOUT);
+                top.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
                 mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
                 return;
             }
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index d151f86..3dff51d 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1901,7 +1901,7 @@
                 "Added restored task=" + task + " to stack=" + stack);
         final ArrayList<ActivityRecord> activities = task.mActivities;
         for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-            activities.get(activityNdx).createAppWindowToken();
+            activities.get(activityNdx).setTask(task);
         }
         return true;
     }
@@ -2123,6 +2123,7 @@
         return false;
     }
 
+    // TODO: Change method name to reflect what it actually does.
     final ArrayList<ActivityRecord> processStoppingActivitiesLocked(ActivityRecord idleActivity,
             boolean remove, boolean processPausingActivities) {
         ArrayList<ActivityRecord> stops = null;
@@ -2131,7 +2132,7 @@
         for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
             ActivityRecord s = mStoppingActivities.get(activityNdx);
 
-            final boolean animating = s.mAppWindowToken.isSelfAnimating();
+            final boolean animating = s.isSelfAnimating();
 
             if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
                     + " animating=" + animating + " finishing=" + s.finishing);
@@ -2482,9 +2483,7 @@
     void activityRelaunchedLocked(IBinder token) {
         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
         if (r != null) {
-            if (r.mAppWindowToken != null) {
-                r.mAppWindowToken.finishRelaunching();
-            }
+            r.finishRelaunching();
             if (r.getActivityStack().shouldSleepOrShutDownActivities()) {
                 r.setSleeping(true, true);
             }
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 54bb5f7..38e5e3e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1684,14 +1684,16 @@
                         == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                         && mLaunchMode == LAUNCH_MULTIPLE;
 
-        // If mStartActivity does not have a task associated with it, associate it with the
-        // reused activity's task. Do not do so if we're clearing top and resetting for a
-        // standard launchMode activity.
-        if (mStartActivity.getTaskRecord() == null && !clearTopAndResetStandardLaunchMode) {
-            mStartActivity.setTask(targetTask);
-        }
-
+        boolean clearTaskForReuse = false;
         if (reusedActivity != null) {
+            // If mStartActivity does not have a task associated with it, associate it with the
+            // reused activity's task. Do not do so if we're clearing top and resetting for a
+            // standard launchMode activity.
+            if (mStartActivity.getTaskRecord() == null && !clearTopAndResetStandardLaunchMode) {
+                mStartActivity.setTaskForReuse(reusedActivity.getTaskRecord());
+                clearTaskForReuse = true;
+            }
+
             if (targetTask.intent == null) {
                 // This task was started because of movement of the activity based on
                 // affinity...
@@ -1739,6 +1741,13 @@
 
         complyActivityFlags(targetTask, reusedActivity);
 
+        if (clearTaskForReuse) {
+            // Clear task for re-use so later code to methods
+            // {@link #setTaskFromReuseOrCreateNewTask}, {@link #setTaskFromSourceRecord}, or
+            // {@link #setTaskFromInTask} can parent it to the task.
+            mStartActivity.setTaskForReuse(null);
+        }
+
         if (mAddingToTask) {
             return START_SUCCESS;
         }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 468a13d..299ab8a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -807,7 +807,7 @@
         mUiHandler = new UiHandler();
         mIntentFirewall = intentFirewall;
         final File systemDir = SystemServiceManager.ensureSystemDir();
-        mAppWarnings = new AppWarnings(this, mUiContext, mH, mUiHandler, systemDir);
+        mAppWarnings = createAppWarnings(mUiContext, mH, mUiHandler, systemDir);
         mCompatModePackages = new CompatModePackages(this, systemDir, mH);
         mPendingIntentController = intentController;
 
@@ -845,6 +845,11 @@
         return supervisor;
     }
 
+    protected AppWarnings createAppWarnings(
+            Context uiContext, Handler handler, Handler uiHandler, File systemDir) {
+        return new AppWarnings(this, uiContext, handler, uiHandler, systemDir);
+    }
+
     public void setWindowManager(WindowManagerService wm) {
         synchronized (mGlobalLock) {
             mWindowManager = wm;
@@ -1813,11 +1818,9 @@
     @Override
     public int getRequestedOrientation(IBinder token) {
         synchronized (mGlobalLock) {
-            ActivityRecord r = ActivityRecord.isInStackLocked(token);
-            if (r == null) {
-                return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-            }
-            return r.getOrientation();
+            final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+            return (r != null)
+                    ? r.getRequestedOrientation() : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2668628..721de61 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -21,8 +21,15 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
+import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
+import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
+import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
+import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
+import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
+import static android.os.Build.VERSION_CODES.HONEYCOMB;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
@@ -62,6 +69,9 @@
 import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
 import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
 import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
+import static com.android.server.wm.IdentifierProto.HASH_CODE;
+import static com.android.server.wm.IdentifierProto.TITLE;
+import static com.android.server.wm.IdentifierProto.USER_ID;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
@@ -84,12 +94,17 @@
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
 
 import android.annotation.CallSuper;
+import android.annotation.Nullable;
 import android.annotation.Size;
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.GraphicBuffer;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
@@ -98,14 +113,13 @@
 import android.os.Build;
 import android.os.Debug;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
+import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
-import android.view.IApplicationToken;
 import android.view.InputApplicationHandle;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
@@ -140,8 +154,8 @@
  * Version of WindowToken that is specifically for a particular application (or
  * really activity) that is displaying windows.
  */
-class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
-        ConfigurationContainerListener {
+// TODO: Fully merge this class into ActivityRecord class since they are really the same thing...
+class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
 
     /**
@@ -149,17 +163,36 @@
      */
     @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
 
+    final ActivityTaskManagerService mAtmService;
     // Non-null only for application tokens.
-    final IApplicationToken appToken;
+    // TODO: rename to mActivityToken
+    final ActivityRecord.Token appToken;
+    // All about me
+    final ActivityInfo mActivityInfo;
+    // Which user is this running for?
+    final int mUserId;
+    // The package implementing intent's component
+    // TODO: rename to mPackageName
+    final String packageName;
+    // the intent component, or target of an alias.
     final ComponentName mActivityComponent;
-    final boolean mVoiceInteraction;
+    boolean mVoiceInteraction;
 
     /**
      * The activity is opaque and fills the entire space of this task.
      * @see WindowContainer#fillsParent()
      */
     private boolean mOccludesParent;
+    // Has a wallpaper window as a background.
+    // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
+    // mOccludesParent field.
+    final boolean hasWallpaper;
+    // activity is not displayed?
+    // TODO: rename to mNoDisplay
+    @VisibleForTesting
+    boolean noDisplay;
     boolean mShowForAllUsers;
+    // TODO: Make this final
     int mTargetSdk;
 
     // Flag set while reparenting to prevent actions normally triggered by an individual parent
@@ -234,10 +267,12 @@
     boolean mLaunchTaskBehind;
     boolean mEnteringAnimation;
 
-    private boolean mAlwaysFocusable;
-
     boolean mAppStopped;
-    int mRotationAnimationHint;
+    // A hint to override the window specified rotation animation, or -1 to use the window specified
+    // value. We use this so that we can select the right animation in the cases of starting
+    // windows, where the app hasn't had time to set a value on the window.
+    int mRotationAnimationHint = -1;
+
     private int mPendingRelaunchCount;
 
     private boolean mLastContainsShowWhenLockedWindow;
@@ -261,9 +296,6 @@
 
     private Task mLastParent;
 
-    // TODO: Remove after unification
-    ActivityRecord mActivityRecord;
-
     /**
      * @see #currentLaunchCanTurnScreenOn()
      */
@@ -327,6 +359,10 @@
     private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
     private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
 
+    private boolean mShowWhenLocked;
+    private boolean mInheritShownWhenLocked;
+    private boolean mTurnScreenOn;
+
     private AppSaturationInfo mLastAppSaturationInfo;
 
     private final ColorDisplayService.ColorTransformController mColorTransformController =
@@ -341,23 +377,67 @@
                 }
             });
 
-    AppWindowToken(WindowManagerService service, IApplicationToken token,
-            ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
-            long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
-            int targetSdk, int orientation, int rotationAnimationHint,
-            boolean launchTaskBehind, boolean alwaysFocusable,
-            ActivityRecord activityRecord) {
-        this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
-        // TODO: remove after unification
-        mActivityRecord = activityRecord;
-        mActivityRecord.registerConfigurationChangeListener(this);
-        mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
-        mShowForAllUsers = showForAllUsers;
-        mTargetSdk = targetSdk;
-        mOrientation = orientation;
-        mLaunchTaskBehind = launchTaskBehind;
-        mAlwaysFocusable = alwaysFocusable;
-        mRotationAnimationHint = rotationAnimationHint;
+    AppWindowToken(WindowManagerService service, ActivityTaskManagerService atm,
+            ActivityRecord.Token token, ActivityInfo aInfo, ActivityOptions options, Intent intent,
+            DisplayContent dc) {
+        super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
+                false /* ownerCanManageAppTokens */);
+        mAtmService = atm;
+        appToken = token;
+        mActivityInfo = aInfo;
+        mUserId = UserHandle.getUserId(mActivityInfo.applicationInfo.uid);
+        packageName = mActivityInfo.applicationInfo.packageName;
+        mInputApplicationHandle = new InputApplicationHandle(appToken);
+
+        // If the class name in the intent doesn't match that of the target, this is probably an
+        // alias. We have to create a new ComponentName object to keep track of the real activity
+        // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
+        if (mActivityInfo.targetActivity == null
+                || (mActivityInfo.targetActivity.equals(intent.getComponent().getClassName())
+                && (mActivityInfo.launchMode == LAUNCH_MULTIPLE
+                || mActivityInfo.launchMode == LAUNCH_SINGLE_TOP))) {
+            mActivityComponent = intent.getComponent();
+        } else {
+            mActivityComponent =
+                    new ComponentName(mActivityInfo.packageName, mActivityInfo.targetActivity);
+        }
+
+        mTargetSdk = mActivityInfo.applicationInfo.targetSdkVersion;
+        mShowForAllUsers = (mActivityInfo.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
+        setOrientation(mActivityInfo.screenOrientation);
+        mRotationAnimationHint = mActivityInfo.rotationAnimation;
+
+        mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
+        mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
+        mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
+
+        int realTheme = mActivityInfo.getThemeResource();
+        if (realTheme == Resources.ID_NULL) {
+            realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
+                    ? android.R.style.Theme : android.R.style.Theme_Holo;
+        }
+
+        final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+                realTheme, com.android.internal.R.styleable.Window, mUserId);
+
+        if (ent != null) {
+            mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
+            hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
+            noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
+        } else {
+            hasWallpaper = false;
+            noDisplay = false;
+        }
+
+        if (options != null) {
+            mLaunchTaskBehind = options.getLaunchTaskBehind();
+
+            final int rotationAnimation = options.getRotationAnimationHint();
+            // Only override manifest supplied option if set.
+            if (rotationAnimation >= 0) {
+                mRotationAnimationHint = rotationAnimation;
+            }
+        }
 
         // Application tokens start out hidden.
         setHidden(true);
@@ -365,20 +445,19 @@
 
         ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
                 ColorDisplayService.ColorDisplayServiceInternal.class);
-        cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
+        cds.attachColorTransformController(packageName, mUserId,
                 new WeakReference<>(mColorTransformController));
     }
 
-    AppWindowToken(WindowManagerService service, IApplicationToken token,
-            ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
-            boolean fillsParent) {
-        super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
-                false /* ownerCanManageAppTokens */);
-        appToken = token;
-        mActivityComponent = activityComponent;
+    void onAttachToTask(boolean voiceInteraction, DisplayContent dc,
+            long inputDispatchingTimeoutNanos) {
+        mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
         mVoiceInteraction = voiceInteraction;
-        mOccludesParent = fillsParent;
-        mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
+        onDisplayChanged(dc);
+
+        // Application tokens start out hidden.
+        setHidden(true);
+        hiddenRequested = true;
     }
 
     void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
@@ -433,43 +512,33 @@
         if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
                 + numInteresting + " visible=" + numVisible);
         if (nowDrawn != reportedDrawn) {
-            if (mActivityRecord != null) {
-                mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
-            }
+            onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
             reportedDrawn = nowDrawn;
         }
         if (nowVisible != reportedVisible) {
             if (DEBUG_VISIBILITY) Slog.v(TAG,
                     "Visibility changed in " + this + ": vis=" + nowVisible);
             reportedVisible = nowVisible;
-            if (mActivityRecord != null) {
-                if (nowVisible) {
-                    onWindowsVisible();
-                } else {
-                    onWindowsGone();
-                }
+            if (nowVisible) {
+                onWindowsVisible();
+            } else {
+                onWindowsGone();
             }
         }
     }
 
-    private void onWindowsGone() {
-        if (mActivityRecord == null) {
-            return;
-        }
-        if (DEBUG_VISIBILITY) {
-            Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
-        }
-        mActivityRecord.onWindowsGone();
+    // Mostly implemented in ActivityRecord.
+    void onWindowsDrawn(boolean drawn, long timestamp) {
     }
 
-    private void onWindowsVisible() {
-        if (mActivityRecord == null) {
-            return;
-        }
-        if (DEBUG_VISIBILITY) {
-            Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
-        }
-        mActivityRecord.onWindowsVisible();
+    // Mostly implemented in ActivityRecord. Keeping here for the logpoint.
+    void onWindowsGone() {
+        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
+    }
+
+    // Mostly implemented in ActivityRecord. Keeping here for the logpoint.
+    void onWindowsVisible() {
+        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
     }
 
     boolean isClientHidden() {
@@ -604,8 +673,6 @@
                     }
                 }
             }
-            // Changes in opening apps and closing apps may cause orientation change.
-            reportDescendantOrientationChangeIfNeeded();
             return;
         }
 
@@ -762,29 +829,27 @@
                 }
                 SurfaceControl.closeTransaction();
             }
-
-            // Visibility changes may cause orientation request change.
-            reportDescendantOrientationChangeIfNeeded();
         }
 
         return delayed;
     }
 
-    private void reportDescendantOrientationChangeIfNeeded() {
+    boolean mayFreezeScreenLocked() {
+        return false;
+    }
+
+    void reportDescendantOrientationChangeIfNeeded() {
         // Orientation request is exposed only when we're visible. Therefore visibility change
         // will change requested orientation. Notify upward the hierarchy ladder to adjust
         // configuration. This is important to cases where activities with incompatible
         // orientations launch, or user goes back from an activity of bi-orientation to an
         // activity with specified orientation.
-        if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
-                || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
+        if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
             return;
         }
 
-        final IBinder freezeToken =
-                mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
-                        ? mActivityRecord.appToken : null;
-        onDescendantOrientationChanged(freezeToken, mActivityRecord);
+        final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
+        onDescendantOrientationChanged(freezeToken, this);
     }
 
     /**
@@ -834,10 +899,16 @@
         return candidate;
     }
 
+    boolean isAlwaysFocusable() {
+        return (mActivityInfo.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
+    }
+
+    // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
+    // focusable means resumeable. I guess with that in mind maybe we should rename the other
+    // method to isResumeable() or something like that.
     boolean windowsAreFocusable() {
         if (mTargetSdk < Build.VERSION_CODES.Q) {
-            final int pid = mActivityRecord != null
-                    ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
+            final int pid = getPid();
             final AppWindowToken topFocusedAppOfMyProcess =
                     mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
             if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
@@ -846,7 +917,12 @@
                 return false;
             }
         }
-        return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
+        return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable();
+    }
+
+    // Mostly implemented in ActivityRecord...
+    int getPid() {
+        return 0;
     }
 
     @Override
@@ -859,9 +935,6 @@
     @Override
     void removeImmediately() {
         onRemovedFromDisplay();
-        if (mActivityRecord != null) {
-            mActivityRecord.unregisterConfigurationChangeListener(this);
-        }
         super.removeImmediately();
     }
 
@@ -1065,7 +1138,9 @@
             if (task == null) {
                 // It is possible we have been marked as a closing app earlier. We must remove ourselves
                 // from this list so we do not participate in any future animations.
-                getDisplayContent().mClosingApps.remove(this);
+                if (getDisplayContent() != null) {
+                    getDisplayContent().mClosingApps.remove(this);
+                }
             } else if (mLastParent != null && mLastParent.mStack != null) {
                 task.mStack.mExitingAppTokens.remove(this);
             }
@@ -1655,7 +1730,7 @@
     }
 
     /** Returns the app's preferred orientation regardless of its currently visibility state. */
-    int getOrientationIgnoreVisibility() {
+    int getRequestedOrientation() {
         return mOrientation;
     }
 
@@ -1669,15 +1744,6 @@
         return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
     }
 
-    /**
-     * @return Non-empty bounds if the activity has override bounds.
-     * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
-     */
-    Rect getResolvedOverrideBounds() {
-        // Get bounds from resolved override configuration because it is computed with orientation.
-        return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
-    }
-
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
         final int prevWinMode = getWindowingMode();
@@ -1708,7 +1774,7 @@
 
         final int winMode = getWindowingMode();
 
-        if (prevWinMode == winMode) {
+        if (prevWinMode == winMode || mDisplayContent == null) {
             return;
         }
 
@@ -1951,8 +2017,9 @@
         }
     }
 
+    // Mostly implemented in ActivityRecord...
     boolean keyDispatchingTimedOut(String reason, int windowPid) {
-        return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
+        return false;
     }
 
     /**
@@ -2019,9 +2086,7 @@
                     }
                 }
             } else if (w.isDrawnLw()) {
-                if (mActivityRecord != null) {
-                    mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
-                }
+                onStartingWindowDrawn(SystemClock.uptimeMillis());
                 startingDisplayed = true;
             }
         }
@@ -2029,6 +2094,14 @@
         return isInterestingAndDrawn;
     }
 
+    /** Called when the starting window for this container is drawn. */
+    private void onStartingWindowDrawn(long timestamp) {
+        synchronized (mAtmService.mGlobalLock) {
+            mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
+                    getWindowingMode(), timestamp);
+        }
+    }
+
     void layoutLetterbox(WindowState winHint) {
         final WindowState w = findMainWindow();
         if (w == null || winHint != null && w != winHint) {
@@ -2413,6 +2486,66 @@
         return false;
     }
 
+    void setShowWhenLocked(boolean showWhenLocked) {
+        mShowWhenLocked = showWhenLocked;
+        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
+                0 /* configChanges */, false /* preserveWindows */);
+    }
+
+    void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
+        mInheritShownWhenLocked = inheritShowWhenLocked;
+        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
+                0 /* configChanges */, false /* preserveWindows */);
+    }
+
+    /**
+     * @return {@code true} if the activity windowing mode is not
+     *         {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
+     *         contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
+     *         activity has set {@link #mShowWhenLocked}, or b) if the activity has set
+     *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
+     *         conditions a) above.
+     *         Multi-windowing mode will be exited if {@code true} is returned.
+     */
+    boolean canShowWhenLocked() {
+        if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
+            return true;
+        } else if (mInheritShownWhenLocked) {
+            final AppWindowToken r = getActivityBelow();
+            return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
+                    || r.containsShowWhenLockedWindow());
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
+     * such activity exists.
+     */
+    @Nullable
+    private AppWindowToken getActivityBelow() {
+        final Task task = getTask();
+        final int pos = task.mChildren.indexOf(this);
+        if (pos == -1) {
+            throw new IllegalStateException("Activity not found in its task");
+        }
+        return pos == 0 ? null : task.getChildAt(pos - 1);
+    }
+
+    void setTurnScreenOn(boolean turnScreenOn) {
+        mTurnScreenOn = turnScreenOn;
+    }
+
+    /** Mostly implemented in ActivityRecord. */
+    boolean canTurnScreenOn() {
+        return mTurnScreenOn;
+    }
+
+    boolean getTurnScreenOnFlag() {
+        return mTurnScreenOn;
+    }
+
     void checkKeyguardFlagsChanged() {
         final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
         final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
@@ -2890,7 +3023,21 @@
         getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
         scheduleAnimation();
 
-        mActivityRecord.onAnimationFinished();
+        if (mAtmService.mRootActivityContainer.allResumedActivitiesIdle()
+                || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
+            // If all activities are already idle or there is an activity that must be
+            // stopped immediately after visible, then we now need to make sure we perform
+            // the full stop of this activity. This is because we won't do that while they are still
+            // waiting for the animation to finish.
+            if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) {
+                mAtmService.mStackSupervisor.scheduleIdleLocked();
+            }
+        } else {
+            // Instead of doing the full stop routine here, let's just hide any activities
+            // we now can, and let them stop when the normal idle happens.
+            mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
+                    false /* remove */, true /* processPausingActivities */);
+        }
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
@@ -2957,10 +3104,13 @@
     }
 
     boolean isWaitingForTransitionStart() {
-        return getDisplayContent().mAppTransition.isTransitionSet()
-                && (getDisplayContent().mOpeningApps.contains(this)
-                    || getDisplayContent().mClosingApps.contains(this)
-                    || getDisplayContent().mChangingApps.contains(this));
+        final DisplayContent dc = getDisplayContent();
+        // TODO: Test for null can be removed once unification is done.
+        if (dc == null) return false;
+        return dc.mAppTransition.isTransitionSet()
+                && (dc.mOpeningApps.contains(this)
+                    || dc.mClosingApps.contains(this)
+                    || dc.mChangingApps.contains(this));
     }
 
     public int getTransit() {
@@ -3204,27 +3354,17 @@
     }
 
     void writeNameToProto(ProtoOutputStream proto, long fieldId) {
-        if (appToken == null) {
-            return;
-        }
-        try {
+        if (appToken != null) {
             proto.write(fieldId, appToken.getName());
-        } catch (RemoteException e) {
-            // This shouldn't happen, but in this case fall back to outputting nothing
-            Slog.e(TAG, e.toString());
         }
     }
 
-    @Override
-    public String toString() {
-        if (stringName == null) {
-            StringBuilder sb = new StringBuilder();
-            sb.append("AppWindowToken{");
-            sb.append(Integer.toHexString(System.identityHashCode(this)));
-            sb.append(" token="); sb.append(token); sb.append('}');
-            stringName = sb.toString();
-        }
-        return stringName + ((mIsExiting) ? " mIsExiting=" : "");
+    void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+        proto.write(HASH_CODE, System.identityHashCode(this));
+        proto.write(USER_ID, mUserId);
+        proto.write(TITLE, ((ActivityRecord) this).intent.getComponent().flattenToShortString());
+        proto.end(token);
     }
 
     Rect getLetterboxInsets() {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 3886ae1..8afbbdf 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -90,7 +90,8 @@
     private ArrayList<ConfigurationContainerListener> mChangeListeners = new ArrayList<>();
 
     // TODO: Can't have ag/2592611 soon enough!
-    private final Configuration mTmpConfig = new Configuration();
+    private final Configuration mRequestsTmpConfig = new Configuration();
+    private final Configuration mResolvedTmpConfig = new Configuration();
 
     // Used for setting bounds
     private final Rect mTmpRect = new Rect();
@@ -121,12 +122,19 @@
      * @see #mFullConfiguration
      */
     public void onConfigurationChanged(Configuration newParentConfig) {
-        mTmpConfig.setTo(mResolvedOverrideConfiguration);
+        onConfigurationChanged(newParentConfig, true /*forwardToChildren*/);
+    }
+
+    // TODO: Consolidate with onConfigurationChanged() method above once unification is done. This
+    // is only currently need during the process of unification where we don't want configuration
+    // forwarded to a child from both parents.
+    public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) {
+        mResolvedTmpConfig.setTo(mResolvedOverrideConfiguration);
         resolveOverrideConfiguration(newParentConfig);
         mFullConfiguration.setTo(newParentConfig);
         mLastOverrideConfigurationChanges =
                 mFullConfiguration.updateFrom(mResolvedOverrideConfiguration);
-        if (!mTmpConfig.equals(mResolvedOverrideConfiguration)) {
+        if (!mResolvedTmpConfig.equals(mResolvedOverrideConfiguration)) {
             onMergedOverrideConfigurationChanged();
             // This depends on the assumption that change-listeners don't do
             // their own override resolution. This way, dependent hierarchies
@@ -139,9 +147,11 @@
                         mResolvedOverrideConfiguration);
             }
         }
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ConfigurationContainer child = getChildAt(i);
-            child.onConfigurationChanged(mFullConfiguration);
+        if (forwardToChildren) {
+            for (int i = getChildCount() - 1; i >= 0; --i) {
+                final ConfigurationContainer child = getChildAt(i);
+                child.onConfigurationChanged(mFullConfiguration);
+            }
         }
     }
 
@@ -262,6 +272,11 @@
         out.set(bounds.left, bounds.top);
     }
 
+    Rect getResolvedOverrideBounds() {
+        mReturnBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
+        return mReturnBounds;
+    }
+
     /**
      * Returns the bounds requested on this container. These may not be the actual bounds the
      * container ends up with due to policy constraints. The {@link Rect} handed back is
@@ -306,9 +321,9 @@
         }
 
 
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setBounds(bounds);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setBounds(bounds);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
 
         return boundsChange;
     }
@@ -360,9 +375,9 @@
 
     /** Sets the requested windowing mode override for the configuration container. */
     public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) {
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setWindowingMode(windowingMode);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setWindowingMode(windowingMode);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
     }
 
     /** Sets the always on top flag for this configuration container.
@@ -372,16 +387,16 @@
      *  - {@Link ActivityDisplay#positionChildAtTop(ActivityStack)};
      * */
     public void setAlwaysOnTop(boolean alwaysOnTop) {
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setAlwaysOnTop(alwaysOnTop);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setAlwaysOnTop(alwaysOnTop);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
     }
 
     /** Sets the windowing mode for the configuration container. */
     void setDisplayWindowingMode(int windowingMode) {
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setDisplayWindowingMode(windowingMode);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setDisplayWindowingMode(windowingMode);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
     }
 
     /**
@@ -451,9 +466,9 @@
             throw new IllegalStateException("Can't change activity type once set: " + this
                     + " activityType=" + activityTypeToString(activityType));
         }
-        mTmpConfig.setTo(getRequestedOverrideConfiguration());
-        mTmpConfig.windowConfiguration.setActivityType(activityType);
-        onRequestedOverrideConfigurationChanged(mTmpConfig);
+        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+        mRequestsTmpConfig.windowConfiguration.setActivityType(activityType);
+        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
     }
 
     public boolean isActivityTypeHome() {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6d9a008..3b90b7e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2635,13 +2635,13 @@
             mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
         }
         for (int i = mOpeningApps.size() - 1; i >= 0; i--) {
-            mOpeningApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, OPENING_APPS);
+            mOpeningApps.valueAt(i).writeIdentifierToProto(proto, OPENING_APPS);
         }
         for (int i = mClosingApps.size() - 1; i >= 0; i--) {
-            mClosingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CLOSING_APPS);
+            mClosingApps.valueAt(i).writeIdentifierToProto(proto, CLOSING_APPS);
         }
         for (int i = mChangingApps.size() - 1; i >= 0; i--) {
-            mChangingApps.valueAt(i).mActivityRecord.writeIdentifierToProto(proto, CHANGING_APPS);
+            mChangingApps.valueAt(i).writeIdentifierToProto(proto, CHANGING_APPS);
         }
         proto.end(token);
     }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 31f4584..0075c15 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -137,9 +137,9 @@
             mStackSupervisor.startSpecificActivityLocked(targetActivity, false /* andResume */,
                     false /* checkConfig */);
             // Make sure the activity won't be involved in transition.
-            if (targetActivity.mAppWindowToken != null) {
-                targetActivity.mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
-                        .appRemovedOrHidden(targetActivity.mAppWindowToken);
+            if (targetActivity.getDisplayContent() != null) {
+                targetActivity.getDisplayContent().mUnknownAppVisibilityController
+                        .appRemovedOrHidden(targetActivity);
             }
         }
 
@@ -429,7 +429,7 @@
         // 1) The next launching task is not being animated by the recents animation
         // 2) The next task is home activity. (i.e. pressing home key to back home in recents).
         if ((!controller.isAnimatingTask(stack.getTaskStack().getTopChild())
-                || controller.isTargetApp(stack.getTopActivity().mAppWindowToken))
+                || controller.isTargetApp(stack.getTopActivity()))
                 && controller.shouldDeferCancelUntilNextTransition()) {
             // Always prepare an app transition since we rely on the transition callbacks to cleanup
             mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 734f224..8a47c5a 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -638,10 +638,16 @@
         if (displayContent != null) {
             config = displayContent.updateOrientation(
                     getDisplayOverrideConfiguration(displayId),
-                    starting != null && starting.mayFreezeScreenLocked(starting.app)
+                    starting != null && starting.mayFreezeScreenLocked()
                             ? starting.appToken : null,
                     true /* forceUpdate */);
         }
+        // Visibilities may change so let the starting activity have a chance to report. Can't do it
+        // when visibility is changed in each AppWindowToken because it may trigger wrong
+        // configuration push because the visibility of some activities may not be updated yet.
+        if (starting != null) {
+            starting.reportDescendantOrientationChangeIfNeeded();
+        }
         if (starting != null && markFrozenIfConfigChanged && config != null) {
             starting.frozenBeforeDestroy = true;
         }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 5e14087..2ad9102 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -20,8 +20,12 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.res.Configuration.EMPTY;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.SurfaceControl.METADATA_TASK_ID;
 
 import static com.android.server.EventLogTags.WM_TASK_REMOVED;
@@ -114,6 +118,13 @@
     // TODO: remove after unification
     TaskRecord mTaskRecord;
 
+    // TODO: Remove after unification.
+    @Override
+    public void onConfigurationChanged(Configuration newParentConfig) {
+        // Only forward configuration changes in cases where children won't get it from TaskRecord.
+        onConfigurationChanged(newParentConfig, mTaskRecord == null /*forwardToChildren*/);
+    }
+
     Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
             boolean supportsPictureInPicture, TaskDescription taskDescription,
             TaskRecord taskRecord) {
@@ -129,11 +140,21 @@
             // unification.
             mTaskRecord.registerConfigurationChangeListener(this);
         }
-        setBounds(getRequestedOverrideBounds());
+        setBounds(getResolvedOverrideBounds());
         mTaskDescription = taskDescription;
 
-        // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
-        setOrientation(SCREEN_ORIENTATION_UNSET);
+        // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED) not unless
+        // set through the override configuration.
+        int orientation = SCREEN_ORIENTATION_UNSET;
+        switch (getResolvedOverrideConfiguration().orientation) {
+            case ORIENTATION_PORTRAIT:
+                orientation = SCREEN_ORIENTATION_PORTRAIT;
+                break;
+            case ORIENTATION_LANDSCAPE:
+                orientation = SCREEN_ORIENTATION_LANDSCAPE;
+                break;
+        }
+        setOrientation(orientation);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 0ea108e..8b2ef7f 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -1251,7 +1251,7 @@
         mActivities.add(newTop);
 
         // Make sure window manager is aware of the position change.
-        mTask.positionChildAtTop(newTop.mAppWindowToken);
+        mTask.positionChildAtTop(newTop);
         updateEffectiveIntent();
     }
 
@@ -1283,7 +1283,7 @@
         r.setTask(this);
 
         // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
-        if (!mActivities.remove(r) && r.fullscreen) {
+        if (!mActivities.remove(r) && r.occludesParent()) {
             // Was not previously in list.
             numFullscreen++;
         }
@@ -1327,10 +1327,10 @@
             mService.notifyTaskPersisterLocked(this, false);
         }
 
-        if (r.mAppWindowToken != null) {
+        if (r.getParent() != null) {
             // Only attempt to move in WM if the child has a controller. It is possible we haven't
             // created controller for the activity we are starting yet.
-            mTask.positionChildAt(r.mAppWindowToken, index);
+            mTask.positionChildAt(r, index);
         }
 
         // Make sure the list of display UID whitelists is updated
@@ -1355,7 +1355,7 @@
 
         r.setTask(null /* task */, reparenting /* reparenting */);
 
-        if (mActivities.remove(r) && r.fullscreen) {
+        if (mActivities.remove(r) && r.occludesParent()) {
             // Was previously in list.
             numFullscreen--;
         }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 264efe0..19fcb1b 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -19,6 +19,11 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
+import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
 import static android.view.SurfaceControl.Transaction;
 
 import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
@@ -33,9 +38,11 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.WindowConfiguration;
+import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.Debug;
 import android.os.IBinder;
 import android.util.Pools;
 import android.util.Slog;
@@ -134,6 +141,8 @@
      */
     private boolean mCommittedReparentToAnimationLeash;
 
+    private final Configuration mTmpConfig = new Configuration();
+
     /**
      * Callback which is triggered while changing the parent, after setting up the surface but
      * before asking the parent to assign child layers.
@@ -260,7 +269,8 @@
         if (child.getParent() != null) {
             throw new IllegalArgumentException("addChild: container=" + child.getName()
                     + " is already a child of container=" + child.getParent().getName()
-                    + " can't add to container=" + getName());
+                    + " can't add to container=" + getName()
+                    + "\n callers=" + Debug.getCallers(15, "\n"));
         }
 
         if ((index < 0 && index != POSITION_BOTTOM)
@@ -751,6 +761,31 @@
     }
 
     /**
+     * Get the configuration orientation by the requested screen orientation
+     * ({@link ActivityInfo.ScreenOrientation}) of this activity.
+     *
+     * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
+     *         {@link Configuration#ORIENTATION_PORTRAIT},
+     *         {@link Configuration#ORIENTATION_UNDEFINED}).
+     */
+    int getRequestedConfigurationOrientation() {
+        if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+            // NOSENSOR means the display's "natural" orientation, so return that.
+            if (mDisplayContent != null) {
+                return mDisplayContent.getNaturalOrientation();
+            }
+        } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
+            // LOCKED means the activity's orientation remains unchanged, so return existing value.
+            return getConfiguration().orientation;
+        } else if (isFixedOrientationLandscape(mOrientation)) {
+            return ORIENTATION_LANDSCAPE;
+        } else if (isFixedOrientationPortrait(mOrientation)) {
+            return ORIENTATION_PORTRAIT;
+        }
+        return ORIENTATION_UNDEFINED;
+    }
+
+    /**
      * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
      * parameters.
      *
@@ -780,6 +815,13 @@
         }
 
         mOrientation = orientation;
+        final int configOrientation = getRequestedConfigurationOrientation();
+        if (getRequestedOverrideConfiguration().orientation != configOrientation) {
+            mTmpConfig.setTo(getRequestedOverrideConfiguration());
+            mTmpConfig.orientation = configOrientation;
+            onRequestedOverrideConfigurationChanged(mTmpConfig);
+        }
+
         final WindowContainer parent = getParent();
         if (parent != null) {
             onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 569d248..1270658 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2424,15 +2424,15 @@
     void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
         // We need to turn on screen regardless of visibility.
         final boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0
-                || (mAppToken != null && mAppToken.mActivityRecord.canTurnScreenOn());
+                || (mAppToken != null && mAppToken.canTurnScreenOn());
 
         // The screen will turn on if the following conditions are met
         // 1. The window has the flag FLAG_TURN_SCREEN_ON or ActivityRecord#canTurnScreenOn.
         // 2. The WMS allows theater mode.
         // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once
         // per resume to prevent the screen getting getting turned on for each relayout. Set
-        // canTurnScreenOn will be set to false so the window doesn't turn the screen on again
-        // during this resume.
+        // currentLaunchCanTurnScreenOn will be set to false so the window doesn't turn the screen
+        // on again during this resume.
         // 4. When the screen is not interactive. This is because when the screen is already
         // interactive, the value may persist until the next animation, which could potentially
         // be occurring while turning off the screen. This would lead to the screen incorrectly
@@ -2617,7 +2617,7 @@
     @Override
     public boolean canShowWhenLocked() {
         final boolean showBecauseOfActivity =
-                mAppToken != null && mAppToken.mActivityRecord.canShowWhenLocked();
+                mAppToken != null && mAppToken.canShowWhenLocked();
         final boolean showBecauseOfWindow = (getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
         return showBecauseOfActivity || showBecauseOfWindow;
     }
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index fbfb028..5b362c3 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -120,7 +120,9 @@
         mPersistOnEmpty = persistOnEmpty;
         mOwnerCanManageAppTokens = ownerCanManageAppTokens;
         mRoundedCornerOverlay = roundedCornerOverlay;
-        onDisplayChanged(dc);
+        if (dc != null) {
+            onDisplayChanged(dc);
+        }
     }
 
     void setHidden(boolean hidden) {