Merge changes I3a966bc7,I91e6832d

* changes:
  Adjust window layout for DisplayCutout
  Display Cutout: Add emulation
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index fac254a..f563794 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.systemui.HardwareUiLayout
+<com.android.systemui.volume.VolumeUiLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -21,18 +21,19 @@
     android:clipChildren="false" >
     <RelativeLayout
         android:id="@+id/volume_dialog"
-        android:layout_width="@dimen/volume_dialog_panel_width"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical|end"
         android:paddingTop="@dimen/volume_row_padding_bottom"
-        android:layout_margin="12dp"
-        android:background="?android:attr/actionBarItemBackground"
-        android:translationZ="8dp" >
+        android:background="@drawable/rounded_full_bg_bottom"
+        android:translationZ="8dp"
+        android:clipChildren="false" >
 
         <LinearLayout
             android:id="@+id/volume_dialog_content"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:clipChildren="false"
+            android:clipToPadding="false"
             android:orientation="vertical" >
 
             <LinearLayout
@@ -42,7 +43,55 @@
                 android:orientation="vertical" >
                 <!-- volume rows added and removed here! :-) -->
             </LinearLayout>
-        </LinearLayout>
 
+            <!-- special row for ringer mode -->
+            <RelativeLayout
+                android:id="@+id/ringer_mode"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:background="@drawable/rounded_bg_full"
+                android:clipChildren="false"
+                android:clipToPadding="false"
+                android:layout_margin="10dp">
+
+                <com.android.keyguard.AlphaOptimizedImageButton
+                    android:id="@+id/ringer_icon"
+                    style="@style/VolumeButtons"
+                    android:background="?android:selectableItemBackgroundBorderless"
+                    android:layout_width="@dimen/volume_button_size"
+                    android:layout_height="@dimen/volume_button_size"
+                    android:layout_alignParentStart="true"
+                    android:layout_centerVertical="true"
+                    android:soundEffectsEnabled="false" />
+
+                <TextView
+                    android:id="@+id/ringer_title"
+                    android:text="@string/stream_ring"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:ellipsize="end"
+                    android:maxLines="1"
+                    android:layout_alignParentStart="true"
+                    android:layout_centerVertical="true"
+                    android:layout_toEndOf="@+id/ringer_icon"
+                    android:layout_marginStart="64dp"
+                    android:textColor="?android:attr/colorControlNormal"
+                    android:textAppearance="?android:attr/textAppearanceSmall"
+                    android:paddingStart="@dimen/volume_row_header_padding_start" />
+
+                <TextView
+                    android:id="@+id/ringer_status"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:ellipsize="end"
+                    android:layout_alignParentEnd="true"
+                    android:layout_centerVertical="true"
+                    android:layout_marginEnd="14dp"
+                    android:maxLines="1"
+                    android:textColor="?android:attr/colorControlNormal"
+                    android:textAppearance="?android:attr/textAppearanceSmall" />
+
+            </RelativeLayout>
+        </LinearLayout>
     </RelativeLayout>
-</com.android.systemui.HardwareUiLayout>
+</com.android.systemui.volume.VolumeUiLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 659c5a8..62ab74d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1248,6 +1248,10 @@
     <string name="stream_tts" translatable="false">Transmitted Through Speaker</string> <!-- STREAM_TTS -->
     <string name="stream_accessibility">Accessibility</string> <!-- STREAM_ACCESSIBILITY -->
 
+    <string name="volume_ringer_status_normal">Ring</string>
+    <string name="volume_ringer_status_vibrate">Vibrate</string>
+    <string name="volume_ringer_status_silent">Mute</string>
+
     <string name="volume_stream_muted" translatable="false">%s silent</string>
     <string name="volume_stream_vibrate" translatable="false">%s vibrate</string>
     <string name="volume_stream_suppressed" translatable="false">%1$s silent — %2$s</string>
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 0d41e20..3e70980 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -30,7 +30,6 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.ColorStateList;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Rect;
@@ -67,8 +66,6 @@
 
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
-import com.android.systemui.HardwareUiLayout;
-import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.plugins.VolumeDialog;
 import com.android.systemui.plugins.VolumeDialogController;
@@ -97,11 +94,12 @@
     private final VolumeDialogController mController;
 
     private Window mWindow;
-    private HardwareUiLayout mHardwareLayout;
     private CustomDialog mDialog;
     private ViewGroup mDialogView;
     private ViewGroup mDialogRowsView;
     private ViewGroup mDialogContentView;
+    private ImageButton mRingerIcon;
+    private TextView mRingerStatus;
     private final List<VolumeRow> mRows = new ArrayList<>();
     private ConfigurableTexts mConfigurableTexts;
     private final SparseBooleanArray mDynamic = new SparseBooleanArray();
@@ -111,6 +109,7 @@
     private final Accessibility mAccessibility = new Accessibility();
     private final ColorStateList mActiveSliderTint;
     private final ColorStateList mInactiveSliderTint;
+    private VolumeUiLayout mHardwareLayout;
 
     private boolean mShowing;
     private boolean mShowA11yStream;
@@ -160,17 +159,34 @@
         mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
         mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
                 | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
-        mWindow.addFlags(
-                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
-                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        mWindow.setTitle(VolumeDialogImpl.class.getSimpleName());
         mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
         mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast);
 
         mDialog.setContentView(R.layout.volume_dialog);
-        mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog);
+        mDialog.setOnShowListener(new DialogInterface.OnShowListener() {
+            @Override
+            public void onShow(DialogInterface dialog) {
+                mDialogView.setTranslationY(-mDialogView.getHeight());
+                mDialogView.setAlpha(0);
+                mDialogView.animate()
+                        .alpha(1)
+                        .translationY(0)
+                        .setDuration(300)
+                        .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
+                        .withEndAction(() -> {
+                            mWindow.getDecorView().requestAccessibilityFocus();
+                        })
+                        .start();
+            }
+        });
+        mDialogView = mDialog.findViewById(R.id.volume_dialog);
         mDialogView.setOnHoverListener(new View.OnHoverListener() {
             @Override
             public boolean onHover(View v, MotionEvent event) {
@@ -181,18 +197,20 @@
                 return true;
             }
         });
-        mHardwareLayout = HardwareUiLayout.get(mDialogView);
+        mHardwareLayout = VolumeUiLayout.get(mDialogView);
         mHardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE));
 
         mDialogContentView = mDialog.findViewById(R.id.volume_dialog_content);
         mDialogRowsView = mDialogContentView.findViewById(R.id.volume_dialog_rows);
+        mRingerIcon = mDialogContentView.findViewById(R.id.ringer_icon);
+        mRingerStatus = mDialogContentView.findViewById(R.id.ringer_status);
 
         if (mRows.isEmpty()) {
             addRow(AudioManager.STREAM_MUSIC,
                     R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true);
             if (!AudioSystem.isSingleVolume(mContext)) {
                 addRow(AudioManager.STREAM_RING,
-                        R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true);
+                        R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, false);
                 addRow(AudioManager.STREAM_ALARM,
                         R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, false);
                 addRow(AudioManager.STREAM_VOICE_CALL,
@@ -208,6 +226,7 @@
             addExistingRows();
         }
         updateRowsH(getActiveRow());
+        initRingerH();
     }
 
     private ColorStateList loadColorStateList(int colorResId) {
@@ -374,6 +393,30 @@
         }
     }
 
+    public void initRingerH() {
+        mRingerIcon.setOnClickListener(v -> {
+            Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, AudioManager.STREAM_RING,
+                    mRingerIcon.getTag());
+            final StreamState ss = mState.states.get(AudioManager.STREAM_RING);
+            final boolean hasVibrator = mController.hasVibrator();
+            if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+                if (hasVibrator) {
+                    mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+                } else {
+                    final boolean wasZero = ss.level == 0;
+                    mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0);
+                }
+            } else {
+                mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+                if (ss.level == 0) {
+                    mController.setStreamVolume(AudioManager.STREAM_RING, 1);
+                }
+            }
+            updateRingerH();
+        });
+        updateRingerH();
+    }
+
     public void show(int reason) {
         mHandler.obtainMessage(H.SHOW, reason, 0).sendToTarget();
     }
@@ -389,27 +432,12 @@
         rescheduleTimeoutH();
         if (mShowing) return;
         mShowing = true;
-        mHardwareLayout.setTranslationX(getAnimTranslation());
-        mHardwareLayout.setAlpha(0);
-        mHardwareLayout.animate()
-                .alpha(1)
-                .translationX(0)
-                .setDuration(300)
-                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                .withEndAction(() -> {
-                    mDialog.show();
-                    mWindow.getDecorView().requestAccessibilityFocus();
-                })
-                .start();
+
+        mDialog.show();
         Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
         mController.notifyVisible(true);
     }
 
-    private float getAnimTranslation() {
-        return mContext.getResources().getDimension(
-                R.dimen.volume_dialog_panel_width) / 2;
-    }
-
     protected void rescheduleTimeoutH() {
         mHandler.removeMessages(H.DISMISS);
         final int timeout = computeTimeoutH();
@@ -423,7 +451,6 @@
         if (mAccessibility.mFeedbackEnabled) return 20000;
         if (mHovering) return 16000;
         if (mSafetyWarning != null) return 5000;
-        if (mActiveStream == AudioManager.STREAM_MUSIC) return 1500;
         return 3000;
     }
 
@@ -431,16 +458,22 @@
         mHandler.removeMessages(H.DISMISS);
         mHandler.removeMessages(H.SHOW);
         if (!mShowing) return;
+        mDialogView.animate().cancel();
         mShowing = false;
-        mHardwareLayout.setTranslationX(0);
-        mHardwareLayout.setAlpha(1);
-        mHardwareLayout.animate()
+
+        mDialogView.setTranslationY(0);
+        mDialogView.setAlpha(1);
+        mDialogView.animate()
                 .alpha(0)
-                .translationX(getAnimTranslation())
-                .setDuration(300)
-                .withEndAction(() -> mDialog.dismiss())
+                .translationY(-mDialogView.getHeight())
+                .setDuration(250)
                 .setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator())
+                .withEndAction(() -> mHandler.postDelayed(() -> {
+                    if (D.BUG) Log.d(TAG, "mDialog.dismiss()");
+                    mDialog.dismiss();
+                }, 50))
                 .start();
+
         if (mAccessibilityMgr.isEnabled()) {
             AccessibilityEvent event =
                     AccessibilityEvent.obtain(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
@@ -493,6 +526,53 @@
         }
     }
 
+    protected void updateRingerH() {
+        if (mState != null) {
+            final StreamState ss = mState.states.get(AudioManager.STREAM_RING);
+            switch (mState.ringerModeInternal) {
+                case AudioManager.RINGER_MODE_VIBRATE:
+                    mRingerStatus.setText(R.string.volume_ringer_status_vibrate);
+                    mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
+                    mRingerIcon.setTag(Events.ICON_STATE_VIBRATE);
+                    break;
+                case AudioManager.RINGER_MODE_SILENT:
+                    mRingerStatus.setText(R.string.volume_ringer_status_silent);
+                    mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
+                    mRingerIcon.setContentDescription(mContext.getString(
+                            R.string.volume_stream_content_description_unmute,
+                            getStreamLabelH(ss)));
+                    mRingerIcon.setTag(Events.ICON_STATE_MUTE);
+                    break;
+                case AudioManager.RINGER_MODE_NORMAL:
+                default:
+                    boolean muted = (mAutomute && ss.level == 0) || ss.muted ? true : false;
+                    if (muted) {
+                        mRingerStatus.setText(R.string.volume_ringer_status_silent);
+                        mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
+                        mRingerIcon.setContentDescription(mContext.getString(
+                                R.string.volume_stream_content_description_unmute,
+                                getStreamLabelH(ss)));
+                        mRingerIcon.setTag(Events.ICON_STATE_MUTE);
+                    } else {
+                        mRingerStatus.setText(R.string.volume_ringer_status_normal);
+                        mRingerIcon.setImageResource(R.drawable.ic_volume_ringer);
+                        if (mController.hasVibrator()) {
+                            mRingerIcon.setContentDescription(mContext.getString(
+                                    mShowA11yStream
+                                            ? R.string.volume_stream_content_description_vibrate_a11y
+                                            : R.string.volume_stream_content_description_vibrate,
+                                    getStreamLabelH(ss)));
+
+                        } else {
+                            mRingerIcon.setContentDescription(getStreamLabelH(ss));
+                        }
+                        mRingerIcon.setTag(Events.ICON_STATE_UNMUTE);
+                    }
+                    break;
+            }
+        }
+    }
+
     private void trimObsoleteH() {
         if (D.BUG) Log.d(TAG, "trimObsoleteH");
         for (int i = mRows.size() - 1; i >= 0; i--) {
@@ -529,6 +609,7 @@
         for (VolumeRow row : mRows) {
             updateVolumeRowH(row);
         }
+        updateRingerH();
     }
 
     private void updateVolumeRowH(VolumeRow row) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
new file mode 100644
index 0000000..49ac9b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.volume;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
+
+public class VolumeUiLayout extends FrameLayout  {
+
+    public VolumeUiLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsListener);
+    }
+
+    @Override
+    public ViewOutlineProvider getOutlineProvider() {
+        return super.getOutlineProvider();
+    }
+
+    public void setOutsideTouchListener(OnClickListener onClickListener) {
+        requestLayout();
+        setOnClickListener(onClickListener);
+        setClickable(true);
+        setFocusable(true);
+    }
+
+    public static VolumeUiLayout get(View v) {
+        if (v instanceof VolumeUiLayout) return (VolumeUiLayout) v;
+        if (v.getParent() instanceof View) {
+            return get((View) v.getParent());
+        }
+        return null;
+    }
+
+    private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
+        inoutInfo.setTouchableInsets(
+                ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
+    };
+}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 7561d0f..723da50 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1239,9 +1239,16 @@
 
     ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
         synchronized (mService) {
-            return mService.getPackageManagerInternalLocked().resolveIntent(intent, resolvedType,
-                    PackageManager.MATCH_INSTANT | PackageManager.MATCH_DEFAULT_ONLY | flags
-                    | ActivityManagerService.STOCK_PM_FLAGS, userId, true);
+            try {
+                Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
+                return mService.getPackageManagerInternalLocked().resolveIntent(
+                        intent, resolvedType, PackageManager.MATCH_INSTANT
+                                | PackageManager.MATCH_DEFAULT_ONLY | flags
+                                | ActivityManagerService.STOCK_PM_FLAGS, userId, true);
+
+            } finally {
+                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index dda8e9c..10fb6e2 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -96,6 +96,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.voice.IVoiceInteractionSession;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ca8ffca..91cad46 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -135,6 +135,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Trace;
 import android.util.DisplayMetrics;
 import android.util.MutableBoolean;
 import android.util.Slog;
@@ -178,20 +179,20 @@
 
     /** The containers below are the only child containers the display can have. */
     // Contains all window containers that are related to apps (Activities)
-    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
+    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(mService);
     // Contains all non-app window containers that should be displayed above the app containers
     // (e.g. Status bar)
     private final AboveAppWindowContainers mAboveAppWindowsContainers =
-            new AboveAppWindowContainers("mAboveAppWindowsContainers");
+            new AboveAppWindowContainers("mAboveAppWindowsContainers", mService);
     // Contains all non-app window containers that should be displayed below the app containers
     // (e.g. Wallpaper).
     private final NonAppWindowContainers mBelowAppWindowsContainers =
-            new NonAppWindowContainers("mBelowAppWindowsContainers");
+            new NonAppWindowContainers("mBelowAppWindowsContainers", mService);
     // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
     // on the IME target. We mainly have this container grouping so we can keep track of all the IME
     // window containers together and move them in-sync if/when needed.
     private final NonAppWindowContainers mImeWindowsContainers =
-            new NonAppWindowContainers("mImeWindowsContainers");
+            new NonAppWindowContainers("mImeWindowsContainers", mService);
 
     private WindowState mTmpWindow;
     private WindowState mTmpWindow2;
@@ -317,8 +318,6 @@
     /** Used for handing back size of display */
     private final Rect mTmpBounds = new Rect();
 
-    WindowManagerService mService;
-
     /** Remove this display when animation on it has completed. */
     private boolean mDeferredRemoval;
 
@@ -765,6 +764,7 @@
      */
     DisplayContent(Display display, WindowManagerService service,
             WallpaperController wallpaperController) {
+        super(service);
         if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
             throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
                     + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
@@ -777,7 +777,6 @@
         display.getDisplayInfo(mDisplayInfo);
         display.getMetrics(mDisplayMetrics);
         isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
-        mService = service;
         mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo);
         initializeDisplayBaseInfo();
         mDividerControllerLocked = new DockedStackDividerController(service, this);
@@ -2339,6 +2338,7 @@
 
     /** Updates the layer assignment of windows on this display. */
     void assignWindowLayers(boolean setLayoutNeeded) {
+        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "assignWindowLayers");
         assignChildLayers(getPendingTransaction());
         if (setLayoutNeeded) {
             setLayoutNeeded();
@@ -2349,6 +2349,7 @@
         // prepareSurfaces. This allows us to synchronize Z-ordering changes with
         // the hiding and showing of surfaces.
         scheduleAnimation();
+        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
     }
 
     // TODO: This should probably be called any time a visual change is made to the hierarchy like
@@ -3182,6 +3183,10 @@
      */
     static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
 
+        DisplayChildWindowContainer(WindowManagerService service) {
+            super(service);
+        }
+
         @Override
         boolean fillsParent() {
             return true;
@@ -3209,6 +3214,10 @@
         private TaskStack mPinnedStack = null;
         private TaskStack mSplitScreenPrimaryStack = null;
 
+        TaskStackContainers(WindowManagerService service) {
+            super(service);
+        }
+
         /**
          * Returns the topmost stack on the display that is compatible with the input windowing mode
          * and activity type. Null is no compatible stack on the display.
@@ -3516,35 +3525,37 @@
 
         @Override
         void assignChildLayers(SurfaceControl.Transaction t) {
-            final int NORMAL_STACK_STATE = 0;
-            final int BOOSTED_STATE = 1;
-            final int ALWAYS_ON_TOP_STATE = 2;
+            int layer = 0;
 
             // We allow stacks to change visual order from the AM specified order due to
             // Z-boosting during animations. However we must take care to ensure TaskStacks
             // which are marked as alwaysOnTop remain that way.
-            int layer = 0;
-            for (int state = 0; state <= ALWAYS_ON_TOP_STATE; state++) {
-                for (int i = 0; i < mChildren.size(); i++) {
-                    final TaskStack s = mChildren.get(i);
-                    layer++;
-                    if (state == NORMAL_STACK_STATE) {
-                        s.assignLayer(t, layer);
-                    } else if (state == BOOSTED_STATE && s.needsZBoost()) {
-                        s.assignLayer(t, layer);
-                    } else if (state == ALWAYS_ON_TOP_STATE &&
-                            s.isAlwaysOnTop()) {
-                        s.assignLayer(t, layer);
-                    }
-                    s.assignChildLayers(t);
+            for (int i = 0; i < mChildren.size(); i++) {
+                final TaskStack s = mChildren.get(i);
+                s.assignChildLayers();
+                if (!s.needsZBoost() && !s.isAlwaysOnTop()) {
+                    s.assignLayer(t, layer++);
                 }
-                // The appropriate place for App-Transitions to occur is right
-                // above all other animations but still below things in the Picture-and-Picture
-                // windowing mode.
-                if (state == BOOSTED_STATE && mAnimationLayer != null) {
-                    t.setLayer(mAnimationLayer, layer + 1);
+            }
+            for (int i = 0; i < mChildren.size(); i++) {
+                final TaskStack s = mChildren.get(i);
+                if (s.needsZBoost() && !s.isAlwaysOnTop()) {
+                    s.assignLayer(t, layer++);
                 }
             }
+            for (int i = 0; i < mChildren.size(); i++) {
+                final TaskStack s = mChildren.get(i);
+                if (s.isAlwaysOnTop()) {
+                    s.assignLayer(t, layer++);
+                }
+            }
+
+            // The appropriate place for App-Transitions to occur is right
+            // above all other animations but still below things in the Picture-and-Picture
+            // windowing mode.
+            if (mAnimationLayer != null) {
+                t.setLayer(mAnimationLayer, layer++);
+            }
         }
 
         @Override
@@ -3560,8 +3571,8 @@
     }
 
     private final class AboveAppWindowContainers extends NonAppWindowContainers {
-        AboveAppWindowContainers(String name) {
-            super(name);
+        AboveAppWindowContainers(String name, WindowManagerService service) {
+            super(name, service);
         }
 
         void assignChildLayers(SurfaceControl.Transaction t, WindowContainer imeContainer) {
@@ -3577,14 +3588,12 @@
 
                 if (needAssignIme && layer >= mService.mPolicy.getWindowLayerFromTypeLw(
                                 TYPE_INPUT_METHOD_DIALOG, true)) {
-                    t.setRelativeLayer(imeContainer.getSurfaceControl(),
-                            wt.getSurfaceControl(), -1);
+                    imeContainer.assignRelativeLayer(t, wt.getSurfaceControl(), -1);
                     needAssignIme = false;
                 }
             }
             if (needAssignIme) {
-                t.setRelativeLayer(imeContainer.getSurfaceControl(),
-                        getSurfaceControl(), Integer.MAX_VALUE);
+                imeContainer.assignRelativeLayer(t, getSurfaceControl(), Integer.MAX_VALUE);
             }
         }
     }
@@ -3618,7 +3627,8 @@
         };
 
         private final String mName;
-        NonAppWindowContainers(String name) {
+        NonAppWindowContainers(String name, WindowManagerService service) {
+            super(service);
             mName = name;
         }
 
@@ -3712,8 +3722,6 @@
 
     @Override
     void assignChildLayers(SurfaceControl.Transaction t) {
-        t.setLayer(mOverlayLayer, 1)
-                .setLayer(mWindowingLayer, 0);
 
         // These are layers as children of "mWindowingLayer"
         mBelowAppWindowsContainers.assignLayer(t, 0);
@@ -3737,8 +3745,7 @@
         // place it in the AboveAppWindowContainers.
         if (imeTarget != null && !imeTarget.inSplitScreenWindowingMode()
                 && (imeTarget.getSurfaceControl() != null)) {
-            t.setRelativeLayer(mImeWindowsContainers.getSurfaceControl(),
-                    imeTarget.getSurfaceControl(),
+            mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
                     // TODO: We need to use an extra level on the app surface to ensure
                     // this is always above SurfaceView but always below attached window.
                     1);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 4008811..b08eb18 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -101,8 +101,6 @@
     private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
     private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
 
-    WindowManagerService mService;
-
     private boolean mWallpaperForceHidingChanged = false;
     private Object mLastWindowFreezeSource = null;
     private Session mHoldScreen = null;
@@ -160,7 +158,7 @@
     };
 
     RootWindowContainer(WindowManagerService service) {
-        mService = service;
+        super(service);
         mHandler = new MyHandler(service.mH.getLooper());
         mWallpaperController = new WallpaperController(mService);
     }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 8aa129a..6ea8a47 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -59,7 +59,6 @@
     final int mTaskId;
     final int mUserId;
     private boolean mDeferRemoval = false;
-    final WindowManagerService mService;
 
     final Rect mPreparedFrozenBounds = new Rect();
     final Configuration mPreparedFrozenMergedConfig = new Configuration();
@@ -102,10 +101,10 @@
     Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
             boolean supportsPictureInPicture, TaskDescription taskDescription,
             TaskWindowContainerController controller) {
+        super(service);
         mTaskId = taskId;
         mStack = stack;
         mUserId = userId;
-        mService = service;
         mResizeMode = resizeMode;
         mSupportsPictureInPicture = supportsPictureInPicture;
         setController(controller);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 94fbd0e..259f8df 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -197,7 +197,7 @@
         }
         try {
             final int res = session.addToDisplay(window, window.mSeq, layoutParams,
-                    View.VISIBLE, token.getDisplayContent().getDisplayId(), tmpRect, tmpRect,
+                    View.GONE, token.getDisplayContent().getDisplayId(), tmpRect, tmpRect,
                     tmpRect, tmpCutout, null);
             if (res < 0) {
                 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 4a3a3fc..832d395 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -75,9 +75,6 @@
     /** Unique identifier */
     final int mStackId;
 
-    /** The service */
-    private final WindowManagerService mService;
-
     /** The display this stack sits under. */
     // TODO: Track parent marks like this in WindowContainer.
     private DisplayContent mDisplayContent;
@@ -151,7 +148,7 @@
     final Rect mTmpDimBoundsRect = new Rect();
 
     TaskStack(WindowManagerService service, int stackId, StackWindowController controller) {
-        mService = service;
+        super(service);
         mStackId = stackId;
         setController(controller);
         mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
diff --git a/services/core/java/com/android/server/wm/TransactionFactory.java b/services/core/java/com/android/server/wm/TransactionFactory.java
new file mode 100644
index 0000000..067f083
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TransactionFactory.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.view.SurfaceControl.Transaction;
+
+/**
+ * Helper class to inject custom transaction objects into window manager.
+ */
+interface TransactionFactory {
+    Transaction make();
+};
+
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index c371e88..d6329bf 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -72,18 +72,25 @@
      WindowContainerController mController;
 
     protected SurfaceControl mSurfaceControl;
+    private int mLastLayer = 0;
+    private SurfaceControl mLastRelativeToLayer = null;
 
     /**
      * Applied as part of the animation pass in "prepareSurfaces".
      */
-    private Transaction mPendingTransaction = new Transaction();
+    private final Transaction mPendingTransaction;
+    protected final WindowManagerService mService;
+
+    WindowContainer(WindowManagerService service) {
+        mService = service;
+        mPendingTransaction = service.mTransactionFactory.make();
+    }
 
     @Override
     final protected WindowContainer getParent() {
         return mParent;
     }
 
-
     @Override
     protected int getChildCount() {
         return mChildren.size();
@@ -756,34 +763,46 @@
     }
 
     void assignLayer(Transaction t, int layer) {
-        if (mSurfaceControl != null) {
+        final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
+        if (mSurfaceControl != null && changed) {
             t.setLayer(mSurfaceControl, layer);
+            mLastLayer = layer;
+            mLastRelativeToLayer = null;
+        }
+    }
+
+    void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
+        final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
+        if (mSurfaceControl != null && changed) {
+            t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
+            mLastLayer = layer;
+            mLastRelativeToLayer = relativeTo;
         }
     }
 
     void assignChildLayers(Transaction t) {
         int layer = 0;
-        boolean boosting = false;
 
         // We use two passes as a way to promote children which
         // need Z-boosting to the end of the list.
-        for (int i = 0; i < 2; i++ ) {
-            for (int j = 0; j < mChildren.size(); ++j) {
-                final WindowContainer wc = mChildren.get(j);
-                if (wc.needsZBoost() && !boosting) {
-                    continue;
-                }
-                wc.assignLayer(t, layer);
-                wc.assignChildLayers(t);
-
-                layer++;
+        for (int j = 0; j < mChildren.size(); ++j) {
+            final WindowContainer wc = mChildren.get(j);
+            wc.assignChildLayers(t);
+            if (!wc.needsZBoost()) {
+                wc.assignLayer(t, layer++);
             }
-            boosting = true;
+        }
+        for (int j = 0; j < mChildren.size(); ++j) {
+            final WindowContainer wc = mChildren.get(j);
+            if (wc.needsZBoost()) {
+                wc.assignLayer(t, layer++);
+            }
         }
     }
 
     void assignChildLayers() {
         assignChildLayers(getPendingTransaction());
+        scheduleAnimation();
     }
 
     boolean needsZBoost() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3ad4df7..e598224 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -215,6 +215,7 @@
 import android.view.PointerIcon;
 import android.view.Surface;
 import android.view.SurfaceControl;
+import android.view.SurfaceControl.Builder;
 import android.view.SurfaceSession;
 import android.view.View;
 import android.view.WindowContentFrameStats;
@@ -806,12 +807,8 @@
     static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
             new WindowManagerThreadPriorityBooster();
 
-    class DefaultSurfaceBuilderFactory implements SurfaceBuilderFactory {
-        public SurfaceControl.Builder make(SurfaceSession s) {
-            return new SurfaceControl.Builder(s);
-        }
-    };
-    SurfaceBuilderFactory mSurfaceBuilderFactory = new DefaultSurfaceBuilderFactory();
+    SurfaceBuilderFactory mSurfaceBuilderFactory = SurfaceControl.Builder::new;
+    TransactionFactory mTransactionFactory = SurfaceControl.Transaction::new;
 
     static void boostPriorityForLockedSection() {
         sThreadPriorityBooster.boost();
@@ -1502,7 +1499,7 @@
 
             // Don't do layout here, the window must call
             // relayout to be displayed, so we'll do it there.
-            displayContent.assignWindowLayers(false /* setLayoutNeeded */);
+            win.getParent().assignChildLayers();
 
             if (focusChanged) {
                 mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
@@ -1972,6 +1969,13 @@
                         + " newVis=" + viewVisibility, stack);
             }
 
+            win.setDisplayLayoutNeeded();
+            win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
+
+            // We may be deferring layout passes at the moment, but since the client is interested
+            // in the new out values right now we need to force a layout.
+            mWindowPlacerLocked.performSurfacePlacement(true /* force */);
+
             // We should only relayout if the view is visible, it is a starting window, or the
             // associated appToken is not hidden.
             final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
@@ -1981,15 +1985,6 @@
             if (shouldRelayout) {
                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
 
-                // We are about to create a surface, but we didn't run a layout yet. So better run
-                // a layout now that we already know the right size, as a resize call will make the
-                // surface transaction blocking until next vsync and slow us down.
-                // TODO: Ideally we'd create the surface after running layout a bit further down,
-                // but moving this seems to be too risky at this point in the release.
-                if (win.mLayoutSeq == -1) {
-                    win.setDisplayLayoutNeeded();
-                    mWindowPlacerLocked.performSurfacePlacement(true);
-                }
                 result = win.relayoutVisibleWindow(result, attrChanges, oldVisibility);
 
                 try {
@@ -2091,16 +2086,11 @@
                 mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken);
             }
 
-            win.setDisplayLayoutNeeded();
-            win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                     "relayoutWindow: updateOrientationFromAppTokens");
             configChanged = updateOrientationFromAppTokensLocked(false, displayId);
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
 
-            // We may be deferring layout passes at the moment, but since the client is interested
-            // in the new out values right now we need to force a layout.
-            mWindowPlacerLocked.performSurfacePlacement(true /* force */);
             if (toBeDisplayed && win.mIsWallpaper) {
                 DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo();
                 dc.mWallpaperController.updateWallpaperOffset(
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d23a6c7..e38605d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -186,7 +186,6 @@
     // to capture touch events in that area.
     static final int RESIZE_HANDLE_WIDTH_IN_DP = 30;
 
-    final WindowManagerService mService;
     final WindowManagerPolicy mPolicy;
     final Context mContext;
     final Session mSession;
@@ -627,7 +626,7 @@
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
-        mService = service;
+        super(service);
         mSession = s;
         mClient = c;
         mAppOp = appOp;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index a3d4b71..5bcf59c 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -46,9 +46,6 @@
 class WindowToken extends WindowContainer<WindowState> {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM;
 
-    // The window manager!
-    protected final WindowManagerService mService;
-
     // The actual token.
     final IBinder token;
 
@@ -107,7 +104,7 @@
 
     WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
             DisplayContent dc, boolean ownerCanManageAppTokens) {
-        mService = service;
+        super(service);
         token = _token;
         windowType = type;
         mPersistOnEmpty = persistOnEmpty;
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
index f069d49..4dd51eb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
@@ -48,6 +48,10 @@
         final SurfaceControl mControl = mock(SurfaceControl.class);
         final SurfaceControl.Transaction mTransaction = mock(SurfaceControl.Transaction.class);
 
+        TestWindowContainer() {
+            super(sWm);
+        }
+
         @Override
         SurfaceControl getSurfaceControl() {
             return mControl;
@@ -65,6 +69,10 @@
         final SurfaceControl mHostControl = mock(SurfaceControl.class);
         final SurfaceControl.Transaction mHostTransaction = mock(SurfaceControl.Transaction.class);
 
+        MockSurfaceBuildingContainer() {
+            super(sWm);
+        }
+
         class MockSurfaceBuilder extends SurfaceControl.Builder {
             MockSurfaceBuilder(SurfaceSession ss) {
                 super(ss);
@@ -78,6 +86,7 @@
             }
         }
 
+
         @Override
         SurfaceControl.Builder makeChildSurface(WindowContainer child) {
             return new MockSurfaceBuilder(mSession);
diff --git a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
index 5da3224..ab0a2bd 100644
--- a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
@@ -34,7 +34,7 @@
  * Test class for {@link StackWindowController}.
  *
  * Build/Install/Run:
- *  bit FrameworksServicesTests:com.android.server.wm.StackWindowControllerTests
+ *  atest FrameworksServicesTests:StackWindowControllerTests
  */
 @SmallTest
 @Presubmit
@@ -61,7 +61,6 @@
     }
 
     @Test
-    @Ignore("b/65379195")
     public void testRemoveContainer_deferRemoval() throws Exception {
         final StackWindowController stackController =
                 createStackControllerOnDisplay(mDisplayContent);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
index 8df7568..bab2170 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
@@ -44,7 +44,7 @@
     @Test
     public void testCreation() throws Exception {
         final WindowContainerController controller = new WindowContainerController(null, sWm);
-        final WindowContainer container = new WindowContainer();
+        final WindowContainer container = new WindowContainer(sWm);
 
         container.setController(controller);
         assertEquals(controller, container.getController());
@@ -54,7 +54,7 @@
     @Test
     public void testSetContainer() throws Exception {
         final WindowContainerController controller = new WindowContainerController(null, sWm);
-        final WindowContainer container = new WindowContainer();
+        final WindowContainer container = new WindowContainer(sWm);
 
         controller.setContainer(container);
         assertEquals(controller.mContainer, container);
@@ -62,7 +62,7 @@
         // Assert we can't change the container to another one once set
         boolean gotException = false;
         try {
-            controller.setContainer(new WindowContainer());
+            controller.setContainer(new WindowContainer(sWm));
         } catch (IllegalArgumentException e) {
             gotException = true;
         }
@@ -76,7 +76,7 @@
     @Test
     public void testRemoveContainer() throws Exception {
         final WindowContainerController controller = new WindowContainerController(null, sWm);
-        final WindowContainer container = new WindowContainer();
+        final WindowContainer container = new WindowContainer(sWm);
 
         controller.setContainer(container);
         assertEquals(controller.mContainer, container);
@@ -88,7 +88,7 @@
     @Test
     public void testOnOverrideConfigurationChanged() throws Exception {
         final WindowContainerController controller = new WindowContainerController(null, sWm);
-        final WindowContainer container = new WindowContainer();
+        final WindowContainer container = new WindowContainer(sWm);
 
         controller.setContainer(container);
         assertEquals(controller.mContainer, container);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index 16b6ca6..5cb9467 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -193,7 +193,7 @@
 
     @Test
     public void testRemoveImmediately_WithController() throws Exception {
-        final WindowContainer container = new WindowContainer();
+        final WindowContainer container = new WindowContainer(sWm);
         final WindowContainerController controller = new WindowContainerController(null, sWm);
 
         container.setController(controller);
@@ -208,7 +208,7 @@
     @Test
     public void testSetController() throws Exception {
         final WindowContainerController controller = new WindowContainerController(null, sWm);
-        final WindowContainer container = new WindowContainer();
+        final WindowContainer container = new WindowContainer(sWm);
 
         container.setController(controller);
         assertEquals(controller, container.getController());
@@ -587,6 +587,7 @@
 
         TestWindowContainer(int layer, boolean isAnimating, boolean isVisible,
             Integer orientation) {
+            super(sWm);
             mLayer = layer;
             mIsAnimating = isAnimating;
             mIsVisible = isVisible;
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index e5cbdba..6468763 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -16,23 +16,6 @@
 
 package com.android.server.wm;
 
-import java.util.HashMap;
-import java.util.LinkedList;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-import android.util.Log;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -42,10 +25,23 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.LinkedList;
 
 /**
  * Tests for the {@link WindowLayersController} class.
@@ -79,7 +75,7 @@
         }
 
         int getLayer(SurfaceControl sc) {
-            return mLayersForControl.get(sc);
+            return mLayersForControl.getOrDefault(sc, 0);
         }
 
         SurfaceControl getRelativeLayer(SurfaceControl sc) {
@@ -125,6 +121,7 @@
         // would miss construction of the top-level layers.
         mTransaction = new LayerRecordingTransaction();
         sWm.mSurfaceBuilderFactory = new HierarchyRecordingBuilderFactory();
+        sWm.mTransactionFactory = () -> mTransaction;
     }
 
     @After