Merge "Promote stable postsubmit tests to presubmit"
diff --git a/core/api/current.txt b/core/api/current.txt
index 1bfb3d5..03c1c19 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1300,6 +1300,7 @@
     field public static final int shortcutLongLabel = 16844074; // 0x101052a
     field public static final int shortcutShortLabel = 16844073; // 0x1010529
     field public static final int shouldDisableView = 16843246; // 0x10101ee
+    field public static final int shouldUseDefaultUnfoldTransition;
     field public static final int showAsAction = 16843481; // 0x10102d9
     field public static final int showDefault = 16843258; // 0x10101fa
     field public static final int showDividers = 16843561; // 0x1010329
@@ -6939,6 +6940,7 @@
     method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
     method public CharSequence loadLabel(android.content.pm.PackageManager);
     method public android.graphics.drawable.Drawable loadThumbnail(android.content.pm.PackageManager);
+    method public boolean shouldUseDefaultUnfoldTransition();
     method public boolean supportsMultipleDisplays();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperInfo> CREATOR;
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index a1a9a2f..e110341 100755
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5440,12 +5440,14 @@
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void clearOnHeadToSoundstagePoseUpdatedListener();
     method @NonNull @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public java.util.List<android.media.AudioDeviceAttributes> getCompatibleAudioDevices();
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public int getDesiredHeadTrackingMode();
+    method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void getEffectParameter(int, @NonNull byte[]);
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public int getHeadTrackingMode();
     method @NonNull @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public java.util.List<java.lang.Integer> getSupportedHeadTrackingModes();
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void recenterHeadTracker();
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void removeCompatibleAudioDevice(@NonNull android.media.AudioDeviceAttributes);
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void removeOnHeadTrackingModeChangedListener(@NonNull android.media.Spatializer.OnHeadTrackingModeChangedListener);
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setDesiredHeadTrackingMode(int);
+    method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setEffectParameter(int, @NonNull byte[]);
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setEnabled(boolean);
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setGlobalTransform(@NonNull float[]);
     method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setOnHeadToSoundstagePoseUpdatedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnHeadToSoundstagePoseUpdatedListener);
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 0703f7c..c330ff7 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -420,10 +420,7 @@
         "android/util/Rational.java",
         "com/android/internal/util/FastXmlSerializer.java",
         "com/android/internal/util/HexDump.java",
-        "com/android/internal/util/IState.java",
         "com/android/internal/util/MessageUtils.java",
-        "com/android/internal/util/State.java",
-        "com/android/internal/util/StateMachine.java",
         "com/android/internal/util/WakeupMessage.java",
     ],
     visibility: [
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index e9b0175..4dff4e0 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -81,6 +81,7 @@
     final int mContextDescriptionResource;
     final boolean mShowMetadataInPreview;
     final boolean mSupportsAmbientMode;
+    final boolean mShouldUseDefaultUnfoldTransition;
     final String mSettingsSliceUri;
     final boolean mSupportMultipleDisplays;
 
@@ -145,6 +146,9 @@
             mSupportsAmbientMode = sa.getBoolean(
                     com.android.internal.R.styleable.Wallpaper_supportsAmbientMode,
                     false);
+            mShouldUseDefaultUnfoldTransition = sa.getBoolean(
+                    com.android.internal.R.styleable.Wallpaper_shouldUseDefaultUnfoldTransition,
+                    true);
             mSettingsSliceUri = sa.getString(
                     com.android.internal.R.styleable.Wallpaper_settingsSliceUri);
             mSupportMultipleDisplays = sa.getBoolean(
@@ -171,6 +175,7 @@
         mSupportsAmbientMode = source.readInt() != 0;
         mSettingsSliceUri = source.readString();
         mSupportMultipleDisplays = source.readInt() != 0;
+        mShouldUseDefaultUnfoldTransition = source.readInt() != 0;
         mService = ResolveInfo.CREATOR.createFromParcel(source);
     }
     
@@ -393,6 +398,26 @@
         return mSupportMultipleDisplays;
     }
 
+    /**
+     * Returns whether this wallpaper should receive default zooming updates when unfolding.
+     * If set to false the wallpaper will not receive zoom events when folding or unfolding
+     * a foldable device, so it can implement its own unfold transition.
+     * <p>
+     * This corresponds to the value {@link
+     * android.R.styleable#Wallpaper_shouldUseDefaultUnfoldTransition} in the XML description
+     * of the wallpaper.
+     * <p>
+     * The default value is {@code true}.
+     *
+     * @see android.R.styleable#Wallpaper_shouldUseDefaultUnfoldTransition
+     * @return {@code true} if wallpaper should receive default fold/unfold transition updates
+     *
+     * @attr ref android.R.styleable#Wallpaper_shouldUseDefaultUnfoldTransition
+     */
+    public boolean shouldUseDefaultUnfoldTransition() {
+        return mShouldUseDefaultUnfoldTransition;
+    }
+
     public void dump(Printer pw, String prefix) {
         pw.println(prefix + "Service:");
         mService.dump(pw, prefix + "  ");
@@ -423,6 +448,7 @@
         dest.writeInt(mSupportsAmbientMode ? 1 : 0);
         dest.writeString(mSettingsSliceUri);
         dest.writeInt(mSupportMultipleDisplays ? 1 : 0);
+        dest.writeInt(mShouldUseDefaultUnfoldTransition ? 1 : 0);
         mService.writeToParcel(dest, flags);
     }
 
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index fe8dc46..e9fffa3 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -27,7 +27,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
@@ -49,6 +48,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 /**
  * Sensor manager implementation that communicates with the built-in
@@ -119,10 +119,11 @@
     private final Looper mMainLooper;
     private final int mTargetSdkLevel;
     private final boolean mIsPackageDebuggable;
-    private final boolean mHasHighSamplingRateSensorsPermission;
     private final Context mContext;
     private final long mNativeInstance;
 
+    private Optional<Boolean> mHasHighSamplingRateSensorsPermission = Optional.empty();
+
     /** {@hide} */
     public SystemSensorManager(Context context, Looper mainLooper) {
         synchronized (sLock) {
@@ -138,11 +139,6 @@
         mContext = context;
         mNativeInstance = nativeCreate(context.getOpPackageName());
         mIsPackageDebuggable = (0 != (appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE));
-        PackageManager packageManager = context.getPackageManager();
-        mHasHighSamplingRateSensorsPermission =
-                (PERMISSION_GRANTED == packageManager.checkPermission(
-                        HIGH_SAMPLING_RATE_SENSORS_PERMISSION,
-                        appInfo.packageName));
 
         // initialize the sensor list
         for (int index = 0;; ++index) {
@@ -153,7 +149,6 @@
         }
     }
 
-
     /** @hide */
     @Override
     protected List<Sensor> getFullSensorList() {
@@ -575,7 +570,7 @@
                 && isSensorInCappedSet(sensor.getType())
                 && rate > CAPPED_SAMPLING_RATE_LEVEL
                 && mIsPackageDebuggable
-                && !mHasHighSamplingRateSensorsPermission
+                && !hasHighSamplingRateSensorsPermission()
                 && Compatibility.isChangeEnabled(CHANGE_ID_SAMPLING_RATE_SENSORS_PERMISSION)) {
             throw new SecurityException("To use the sampling rate level " + rate
                     + ", app needs to declare the normal permission"
@@ -787,7 +782,7 @@
             if (mManager.isSensorInCappedSet(sensor.getType())
                     && rateUs < CAPPED_SAMPLING_PERIOD_US
                     && mManager.mIsPackageDebuggable
-                    && !mManager.mHasHighSamplingRateSensorsPermission
+                    && !mManager.hasHighSamplingRateSensorsPermission()
                     && Compatibility.isChangeEnabled(CHANGE_ID_SAMPLING_RATE_SENSORS_PERMISSION)) {
                 throw new SecurityException("To use the sampling rate of " + rateUs
                         + " microseconds, app needs to declare the normal permission"
@@ -1034,4 +1029,15 @@
                 || sensorType == Sensor.TYPE_MAGNETIC_FIELD
                 || sensorType == Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);
     }
+
+    private boolean hasHighSamplingRateSensorsPermission() {
+        if (!mHasHighSamplingRateSensorsPermission.isPresent()) {
+            boolean granted = mContext.getPackageManager().checkPermission(
+                    HIGH_SAMPLING_RATE_SENSORS_PERMISSION,
+                    mContext.getApplicationInfo().packageName) == PERMISSION_GRANTED;
+            mHasHighSamplingRateSensorsPermission = Optional.of(granted);
+        }
+
+        return mHasHighSamplingRateSensorsPermission.get();
+    }
 }
diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
index 9a9e945..16adee9 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -295,6 +295,16 @@
         }
 
         @Override
+        public int getMessageHistorySize() {
+            return HdmiControlServiceWrapper.this.getMessageHistorySize();
+        }
+
+        @Override
+        public boolean setMessageHistorySize(int newSize) {
+            return HdmiControlServiceWrapper.this.setMessageHistorySize(newSize);
+        }
+
+        @Override
         public void addCecSettingChangeListener(String name,
                 IHdmiCecSettingChangeListener listener) {
             HdmiControlServiceWrapper.this.addCecSettingChangeListener(name, listener);
@@ -523,6 +533,16 @@
             IHdmiCecVolumeControlFeatureListener listener) {}
 
     /** @hide */
+    public int getMessageHistorySize() {
+        return 0;
+    }
+
+    /** @hide */
+    public boolean setMessageHistorySize(int newSize) {
+        return true;
+    }
+
+    /** @hide */
     public void addCecSettingChangeListener(String name,
             IHdmiCecSettingChangeListener listener) {}
 
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 7f0e53e..6613397 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -88,6 +88,8 @@
     void setStandbyMode(boolean isStandbyModeOn);
     void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute);
     void setSystemAudioModeOnForAudioOnlySource();
+    boolean setMessageHistorySize(int newSize);
+    int getMessageHistorySize();
     void addCecSettingChangeListener(String name, IHdmiCecSettingChangeListener listener);
     void removeCecSettingChangeListener(String name, IHdmiCecSettingChangeListener listener);
     List<String> getUserCecSettings();
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index 43ea2e7..9f799f9e 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -282,7 +282,7 @@
             case USAGE_ALARM:
                 return "ALARM";
             case USAGE_RINGTONE:
-                return "RIGNTONE";
+                return "RINGTONE";
             case USAGE_NOTIFICATION:
                 return "NOTIFICATION";
             case USAGE_COMMUNICATION_REQUEST:
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index 54905ec..8928a42 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.os.IVold;
 
 import java.util.List;
@@ -135,4 +136,19 @@
      * {@link VolumeInfo#isPrimary()}
      */
     public abstract List<String> getPrimaryVolumeIds();
+
+    /**
+     * Tells StorageManager that CE storage for this user has been prepared.
+     *
+     * @param userId userId for which CE storage has been prepared
+     */
+    public abstract void markCeStoragePrepared(@UserIdInt int userId);
+
+    /**
+     * Returns true when CE storage for this user has been prepared.
+     *
+     * When the user key is unlocked and CE storage has been prepared,
+     * it's ok to access and modify CE directories on volumes for this user.
+     */
+    public abstract boolean isCeStoragePrepared(@UserIdInt int userId);
 }
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index a47c3b1..491a5f9 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -920,6 +920,13 @@
 
         if (!mWaking && !mFinished) {
             mWaking = true;
+            // During wake up the activity should be translucent to allow the application underneath
+            // to start drawing. Normally, the WM animation system takes care of this, but here we
+            // give the dream application some time to perform a custom exit animation.
+            // If it uses a view animation, the WM doesn't know about it and can't make the activity
+            // translucent in the normal way. Therefore, here we ensure that the activity is
+            // translucent during wake up regardless of what animation is used in onWakeUp().
+            mActivity.convertToTranslucent(null, null);
 
             // As a minor optimization, invoke the callback first in case it simply
             // calls finish() immediately so there wouldn't be much point in telling
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index bc2bac3..0ef71f1 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8370,6 +8370,17 @@
              @hide @SystemApi -->
         <attr name="supportsAmbientMode" format="boolean" />
 
+        <!-- Indicates that this wallpaper service should receive zoom updates when unfolding.
+             When this value is set to true
+             {@link android.service.wallpaper.WallpaperService.Engine} could receive zoom updates
+             when folding or unfolding a foldable device. Wallpapers receive zoom updates using
+             {@link android.service.wallpaper.WallpaperService.Engine#onZoomChanged(float)} and
+             zoom rendering should be handled manually. Default value is true.
+             When set to false wallpapers can implement custom folding/unfolding behavior
+             by listening to {@link android.hardware.Sensor#TYPE_HINGE_ANGLE}.
+             Corresponds to {@link android.app.WallpaperInfo#shouldUseDefaultUnfoldTransition()} -->
+        <attr name="shouldUseDefaultUnfoldTransition" format="boolean" />
+
         <!-- Uri that specifies a settings Slice for this wallpaper. -->
         <attr name="settingsSliceUri" format="string"/>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e28288d..7e6ea7a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3221,6 +3221,7 @@
   <eat-comment />
 
   <staging-public-group type="attr" first-id="0x01ff0000">
+    <public name="shouldUseDefaultUnfoldTransition" />
   </staging-public-group>
 
   <staging-public-group type="id" first-id="0x01fe0000">
diff --git a/core/tests/coretests/src/android/view/KeyEventTest.java b/core/tests/coretests/src/android/view/KeyEventTest.java
index 98ab592..bbb25a3 100644
--- a/core/tests/coretests/src/android/view/KeyEventTest.java
+++ b/core/tests/coretests/src/android/view/KeyEventTest.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertFalse;
 
 import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
@@ -34,6 +35,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@Presubmit
 public class KeyEventTest {
 
     private static final int DOWN_TIME = 50;
diff --git a/core/tests/coretests/src/android/view/MotionEventTest.java b/core/tests/coretests/src/android/view/MotionEventTest.java
index b3450de..7f7a7aa 100644
--- a/core/tests/coretests/src/android/view/MotionEventTest.java
+++ b/core/tests/coretests/src/android/view/MotionEventTest.java
@@ -26,6 +26,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 
+import android.platform.test.annotations.Presubmit;
 import android.view.MotionEvent.PointerCoords;
 import android.view.MotionEvent.PointerProperties;
 
@@ -40,6 +41,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@Presubmit
 public class MotionEventTest {
     private static final int ID_SOURCE_MASK = 0x3 << 30;
 
@@ -174,6 +176,7 @@
     public void testEventRotation() {
         final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */,
                     ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */);
+        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
         MotionEvent rot90 = MotionEvent.obtain(event);
         rot90.transform(MotionEvent.createRotateMatrix(/* 90 deg */1, 1000, 600));
         assertEquals(50, (int) rot90.getX());
diff --git a/core/tests/coretests/src/android/view/VerifiedKeyEventTest.kt b/core/tests/coretests/src/android/view/VerifiedKeyEventTest.kt
index 531d55d..86ff2da 100644
--- a/core/tests/coretests/src/android/view/VerifiedKeyEventTest.kt
+++ b/core/tests/coretests/src/android/view/VerifiedKeyEventTest.kt
@@ -19,6 +19,7 @@
 import android.view.InputDevice.SOURCE_KEYBOARD
 import android.view.KeyEvent.ACTION_DOWN
 import android.os.Parcel
+import android.platform.test.annotations.Presubmit
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -30,6 +31,7 @@
 
 @RunWith(AndroidJUnit4::class)
 @SmallTest
+@Presubmit
 class VerifiedKeyEventTest {
 
     @Test
diff --git a/core/tests/coretests/src/android/view/VerifiedMotionEventTest.kt b/core/tests/coretests/src/android/view/VerifiedMotionEventTest.kt
index 29ad0aa..97870ee 100644
--- a/core/tests/coretests/src/android/view/VerifiedMotionEventTest.kt
+++ b/core/tests/coretests/src/android/view/VerifiedMotionEventTest.kt
@@ -23,6 +23,7 @@
 import android.view.MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED
 import android.view.MotionEvent.FLAG_TAINTED
 import android.os.Parcel
+import android.platform.test.annotations.Presubmit
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -35,6 +36,7 @@
 
 @RunWith(AndroidJUnit4::class)
 @SmallTest
+@Presubmit
 class VerifiedMotionEventTest {
 
     @Test
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 597ea14..f04a9f7 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -376,6 +376,17 @@
         }
 
         @Override
+        public int getMessageHistorySize() {
+            return 0;
+        }
+
+        @Override
+        public boolean setMessageHistorySize(int newSize) {
+            return true;
+        }
+
+
+        @Override
         public List<String> getUserCecSettings() {
             return new ArrayList<>();
         }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index e736dce..c07f0eb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+@file:JvmName("CommonAssertions")
 package com.android.wm.shell.flicker
 
 import android.graphics.Region
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt
index a6d6735..b63d9ff 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+@file:JvmName("WaitUtils")
 package com.android.wm.shell.flicker
 
 import android.os.SystemClock
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
index 19374ed..038be9c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
@@ -100,8 +100,8 @@
             "Non resizeable app not initialized"
         }
         testSpec.assertWmEnd {
-            isVisible(nonResizeableApp.component)
-            isInvisible(primaryApp.component)
+            isAppWindowVisible(nonResizeableApp.component)
+            isAppWindowInvisible(primaryApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
index 46ee892..bbc6b2d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
@@ -77,8 +77,8 @@
     @Test
     fun bothAppWindowsVisible() {
         testSpec.assertWmEnd {
-            isVisible(primaryApp.component)
-            isVisible(secondaryApp.component)
+            isAppWindowVisible(primaryApp.component)
+            isAppWindowVisible(secondaryApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt
index f7ced71..bb784a8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt
@@ -100,8 +100,8 @@
             "Non resizeable app not initialized"
         }
         testSpec.assertWmEnd {
-            isVisible(nonResizeableApp.component)
-            isVisible(primaryApp.component)
+            isAppWindowVisible(nonResizeableApp.component)
+            isAppWindowVisible(primaryApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
index 3debdd3..a1a4db1 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
@@ -81,8 +81,8 @@
     @Test
     fun bothAppWindowsInvisible() {
         testSpec.assertWmEnd {
-            isInvisible(primaryApp.component)
-            isInvisible(secondaryApp.component)
+            isAppWindowInvisible(primaryApp.component)
+            isAppWindowInvisible(secondaryApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
index 3e782e6..56a2531 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
@@ -73,8 +73,8 @@
     @Test
     fun bothAppWindowsVisible() {
         testSpec.assertWmEnd {
-            isVisible(primaryApp.component)
-                .isVisible(secondaryApp.component)
+            isAppWindowVisible(primaryApp.component)
+            isAppWindowVisible(secondaryApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
index ee28c7a..0699a4f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
@@ -85,8 +85,8 @@
     @Test
     fun bothAppWindowsVisible() {
         testSpec.assertWmEnd {
-            isVisible(primaryApp.component)
-            isVisible(secondaryApp.component)
+            isAppWindowVisible(primaryApp.component)
+            isAppWindowVisible(secondaryApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
index cad38ad..bd44d08 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
@@ -88,7 +88,7 @@
     @Test
     fun appWindowIsVisible() {
         testSpec.assertWmEnd {
-            isVisible(splitScreenApp.component)
+            isAppWindowVisible(splitScreenApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt
index b60cbcf..625d48b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt
@@ -77,7 +77,7 @@
     @Test
     fun appWindowIsVisible() {
         testSpec.assertWmEnd {
-            isVisible(splitScreenApp.component)
+            isAppWindowVisible(splitScreenApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
index 94ae9da..2ed2806 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
@@ -91,7 +91,7 @@
             // Because we log WM once per frame, sometimes the activity and the window
             // become visible in the same entry, sometimes not, thus it is not possible to
             // assert the visibility of the activity here
-            this.isAppWindowInvisible(secondaryApp.component, ignoreActivity = true)
+            this.isAppWindowInvisible(secondaryApp.component)
                     .then()
                     // during re-parenting, the window may disappear and reappear from the
                     // trace, this occurs because we log only 1x per frame
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenSupportNonResizable.kt
index 2beb8a9..163b6ffda 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenSupportNonResizable.kt
@@ -94,7 +94,7 @@
     @Test
     fun appWindowIsVisible() {
         testSpec.assertWmEnd {
-            isVisible(nonResizeableApp.component)
+            isAppWindowVisible(nonResizeableApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentNotSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentNotSupportNonResizable.kt
index 6bc717a..f7d628d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentNotSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentNotSupportNonResizable.kt
@@ -119,12 +119,12 @@
             // when the activity gets PAUSED the window may still be marked as visible
             // it will be updated in the next log entry. This occurs because we record 1x
             // per frame, thus ignore activity check here
-            this.isAppWindowVisible(splitScreenApp.component, ignoreActivity = true)
+            this.isAppWindowVisible(splitScreenApp.component)
                     .then()
                     // immediately after the window (after onResume and before perform relayout)
                     // the activity is invisible. This may or not be logged, since we record 1x
                     // per frame, thus ignore activity check here
-                    .isAppWindowInvisible(splitScreenApp.component, ignoreActivity = true)
+                    .isAppWindowInvisible(splitScreenApp.component)
         }
     }
 
@@ -141,13 +141,12 @@
                     .then()
                     // we log once per frame, upon logging, window may be visible or not depending
                     // on what was processed until that moment. Both behaviors are correct
-                    .isAppWindowInvisible(nonResizeableApp.component,
-                            ignoreActivity = true, isOptional = true)
+                    .isAppWindowInvisible(nonResizeableApp.component, isOptional = true)
                     .then()
                     // immediately after the window (after onResume and before perform relayout)
                     // the activity is invisible. This may or not be logged, since we record 1x
                     // per frame, thus ignore activity check here
-                    .isAppWindowVisible(nonResizeableApp.component, ignoreActivity = true)
+                    .isAppWindowVisible(nonResizeableApp.component)
         }
     }
 
@@ -158,7 +157,7 @@
     @Test
     fun nonResizableAppWindowBecomesVisibleAtEnd() {
         testSpec.assertWmEnd {
-            this.isVisible(nonResizeableApp.component)
+            isAppWindowVisible(nonResizeableApp.component)
         }
     }
 
@@ -170,8 +169,8 @@
     @Test
     fun onlyNonResizableAppWindowIsVisibleAtEnd() {
         testSpec.assertWmEnd {
-            isInvisible(splitScreenApp.component)
-            isVisible(nonResizeableApp.component)
+            isAppWindowInvisible(splitScreenApp.component)
+            isAppWindowVisible(nonResizeableApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentSupportNonResizable.kt
index 212acc7..a5c6571 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromIntentSupportNonResizable.kt
@@ -109,13 +109,12 @@
                     .then()
                     // we log once per frame, upon logging, window may be visible or not depending
                     // on what was processed until that moment. Both behaviors are correct
-                    .isAppWindowInvisible(nonResizeableApp.component,
-                            ignoreActivity = true, isOptional = true)
+                    .isAppWindowInvisible(nonResizeableApp.component, isOptional = true)
                     .then()
                     // immediately after the window (after onResume and before perform relayout)
                     // the activity is invisible. This may or not be logged, since we record 1x
                     // per frame, thus ignore activity check here
-                    .isAppWindowVisible(nonResizeableApp.component, ignoreActivity = true)
+                    .isAppWindowVisible(nonResizeableApp.component)
         }
     }
 
@@ -127,8 +126,8 @@
     @Test
     fun bothAppsWindowsAreVisibleAtEnd() {
         testSpec.assertWmEnd {
-            isVisible(splitScreenApp.component)
-            isVisible(nonResizeableApp.component)
+            isAppWindowVisible(splitScreenApp.component)
+            isAppWindowVisible(nonResizeableApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt
index 6912960..6f486b0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt
@@ -115,12 +115,12 @@
             // when the activity gets PAUSED the window may still be marked as visible
             // it will be updated in the next log entry. This occurs because we record 1x
             // per frame, thus ignore activity check here
-            this.isAppWindowVisible(splitScreenApp.component, ignoreActivity = true)
+            this.isAppWindowVisible(splitScreenApp.component)
                     .then()
                     // immediately after the window (after onResume and before perform relayout)
                     // the activity is invisible. This may or not be logged, since we record 1x
                     // per frame, thus ignore activity check here
-                    .isAppWindowInvisible(splitScreenApp.component, ignoreActivity = true)
+                    .isAppWindowInvisible(splitScreenApp.component)
         }
     }
 
@@ -142,8 +142,8 @@
     @Test
     fun onlyNonResizableAppWindowIsVisibleAtEnd() {
         testSpec.assertWmEnd {
-            isInvisible(splitScreenApp.component)
-            isVisible(nonResizeableApp.component)
+            isAppWindowInvisible(splitScreenApp.component)
+            isAppWindowVisible(nonResizeableApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentSupportNonResizable.kt
index b7a78ce..f03c927 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentSupportNonResizable.kt
@@ -106,7 +106,7 @@
             // Because we log WM once per frame, sometimes the activity and the window
             // become visible in the same entry, sometimes not, thus it is not possible to
             // assert the visibility of the activity here
-            this.isAppWindowInvisible(nonResizeableApp.component, ignoreActivity = true)
+            this.isAppWindowInvisible(nonResizeableApp.component)
                     .then()
                     // during re-parenting, the window may disappear and reappear from the
                     // trace, this occurs because we log only 1x per frame
@@ -128,8 +128,8 @@
     @Test
     fun bothAppsWindowsAreVisibleAtEnd() {
         testSpec.assertWmEnd {
-            isVisible(splitScreenApp.component)
-            isVisible(nonResizeableApp.component)
+            isAppWindowVisible(splitScreenApp.component)
+            isAppWindowVisible(nonResizeableApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
index cb2e8039..2abdca9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
@@ -97,7 +97,7 @@
             // Because we log WM once per frame, sometimes the activity and the window
             // become visible in the same entry, sometimes not, thus it is not possible to
             // assert the visibility of the activity here
-            this.isAppWindowInvisible(secondaryApp.component, ignoreActivity = true)
+            this.isAppWindowInvisible(secondaryApp.component)
                     .then()
                     // during re-parenting, the window may disappear and reappear from the
                     // trace, this occurs because we log only 1x per frame
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/CommonAssertions.kt
index 443204c2..f9b0800 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/CommonAssertions.kt
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+@file:JvmName("CommonAssertions")
 package com.android.wm.shell.flicker.pip
 
 internal const val PIP_WINDOW_COMPONENT = "PipMenuActivity"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index 7ef0eef..c8c3f4d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -148,7 +148,7 @@
     @Test
     fun testAppWindowInvisibleOnStart() {
         testSpec.assertWmStart {
-            isInvisible(testApp.component)
+            isAppWindowInvisible(testApp.component)
         }
     }
 
@@ -159,7 +159,7 @@
     @Test
     fun testAppWindowVisibleOnEnd() {
         testSpec.assertWmEnd {
-            isVisible(testApp.component)
+            isAppWindowVisible(testApp.component)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index 8d21d83..64b7eb5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -62,7 +62,7 @@
             // when the activity is STOPPING, sometimes it becomes invisible in an entry before
             // the window, sometimes in the same entry. This occurs because we log 1x per frame
             // thus we ignore activity here
-            isAppWindowVisible(testApp.component, ignoreActivity = true)
+            isAppWindowVisible(testApp.component)
                     .isAppWindowOnTop(pipApp.component)
                     .then()
                     .isAppWindowInvisible(testApp.component)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
index 3414031..5207fed 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
@@ -54,9 +54,9 @@
     open fun pipWindowBecomesInvisible() {
         testSpec.assertWm {
             this.invoke("hasPipWindow") {
-                it.isPinned(pipApp.component).isVisible(pipApp.component)
+                it.isPinned(pipApp.component).isAppWindowVisible(pipApp.component)
             }.then().invoke("!hasPipWindow") {
-                it.isNotPinned(pipApp.component).isInvisible(pipApp.component)
+                it.isNotPinned(pipApp.component).isAppWindowInvisible(pipApp.component)
             }
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index d6030401..9bea5c0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -104,9 +104,9 @@
     @Test
     fun bothAppWindowsVisible() {
         testSpec.assertWmEnd {
-            isVisible(testApp.component)
-            isVisible(imeApp.component)
-            noWindowsOverlap(testApp.component, imeApp.component)
+            isAppWindowVisible(testApp.component)
+            isAppWindowVisible(imeApp.component)
+            doNotOverlap(testApp.component, imeApp.component)
         }
     }
 
diff --git a/location/java/android/location/OnNmeaMessageListener.java b/location/java/android/location/OnNmeaMessageListener.java
index 05647bc..1c02ebd 100644
--- a/location/java/android/location/OnNmeaMessageListener.java
+++ b/location/java/android/location/OnNmeaMessageListener.java
@@ -16,14 +16,17 @@
 
 package android.location;
 
+import java.util.concurrent.Executor;
+
 /**
-* Used for receiving NMEA sentences from the GNSS.
-* NMEA 0183 is a standard for communicating with marine electronic devices
-* and is a common method for receiving data from a GNSS, typically over a serial port.
-* See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
-* You can implement this interface and call {@link LocationManager#addNmeaListener}
-* to receive NMEA data from the GNSS engine.
-*/
+ * Used for receiving NMEA sentences from the GNSS.
+ * NMEA 0183 is a standard for communicating with marine electronic devices
+ * and is a common method for receiving data from a GNSS, typically over a serial port.
+ * See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
+ * You can implement this interface and call
+ * {@link LocationManager#addNmeaListener(Executor, OnNmeaMessageListener)} to receive NMEA data
+ * from the GNSS engine.
+ */
 public interface OnNmeaMessageListener {
     /**
      * Called when an NMEA message is received.
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5419d6c..7604b360 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -445,4 +445,8 @@
     oneway void setSpatializerGlobalTransform(in float[] transform);
 
     oneway void recenterHeadTracker();
+
+    void setSpatializerParameter(int key, in byte[] value);
+
+    void getSpatializerParameter(int key, inout byte[] value);
 }
diff --git a/media/java/android/media/Spatializer.java b/media/java/android/media/Spatializer.java
index b062eea..3b835f7 100644
--- a/media/java/android/media/Spatializer.java
+++ b/media/java/android/media/Spatializer.java
@@ -792,6 +792,45 @@
         }
     }
 
+    /**
+     * @hide
+     * Sets a parameter on the platform spatializer effect implementation.
+     * This is to be used for vendor-specific configurations of their effect, keys and values are
+     * not reuseable across implementations.
+     * @param key the parameter to change
+     * @param value an array for the value of the parameter to change
+     */
+    @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
+    @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
+    public void setEffectParameter(int key, @NonNull byte[] value) {
+        Objects.requireNonNull(value);
+        try {
+            mAm.getService().setSpatializerParameter(key, value);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling setEffectParameter", e);
+        }
+    }
+
+    /**
+     * @hide
+     * Retrieves a parameter value from the platform spatializer effect implementation.
+     * This is to be used for vendor-specific configurations of their effect, keys and values are
+     * not reuseable across implementations.
+     * @param key the parameter for which the value is queried
+     * @param value a non-empty array to contain the return value. The caller is responsible for
+     *              passing an array of size matching the parameter.
+     */
+    @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
+    @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
+    public void getEffectParameter(int key, @NonNull byte[] value) {
+        Objects.requireNonNull(value);
+        try {
+            mAm.getService().getSpatializerParameter(key, value);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling getEffectParameter", e);
+        }
+    }
+
     //-----------------------------------------------------------------------------
     // callback helper definitions
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
index 4361b96..5510e73 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
@@ -16,12 +16,6 @@
 
 package com.android.mediaframeworktest.functional;
 
-
-
-//import android.content.Resources;
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import com.android.mediaframeworktest.MediaNames;
-
 import android.content.res.AssetFileDescriptor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -36,15 +30,12 @@
 import android.os.SystemClock;
 import android.util.Log;
 
-import java.io.File;
-import java.io.FileWriter;
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.io.FileOutputStream;
 import java.util.HashSet;
-import java.util.Random;
 import java.util.Set;
 /**
  * Junit / Instrumentation test case for the media player api
@@ -539,14 +530,16 @@
         try{
             BitmapFactory mBitmapFactory = new BitmapFactory();
 
-            MediaMetadataRetriever mMediaMetadataRetriever = new MediaMetadataRetriever();
-            try {
-                mMediaMetadataRetriever.setDataSource(filePath);
-            } catch(Exception e) {
-                e.printStackTrace();
-                return false;
+            Bitmap outThumbnail;
+            try (MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever()) {
+                try {
+                    mediaMetadataRetriever.setDataSource(filePath);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return false;
+                }
+                outThumbnail = mediaMetadataRetriever.getFrameAtTime(-1);
             }
-            Bitmap outThumbnail = mMediaMetadataRetriever.getFrameAtTime(-1);
 
             //Verify the thumbnail
             Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath);
@@ -567,7 +560,7 @@
                     return false;
                 }
            }
-        }catch (Exception e){
+        } catch (Exception e) {
             Log.v(TAG, e.toString());
             return false;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
index 2d215e0..a424674 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
@@ -100,8 +100,7 @@
      */
     public void updateIndication(@IndicationType int type, KeyguardIndication newIndication,
             boolean updateImmediately) {
-        if (type == INDICATION_TYPE_NOW_PLAYING
-                || type == INDICATION_TYPE_REVERSE_CHARGING) {
+        if (type == INDICATION_TYPE_REVERSE_CHARGING) {
             // temporarily don't show here, instead use AmbientContainer b/181049781
             return;
         }
@@ -303,7 +302,6 @@
     public static final int INDICATION_TYPE_TRUST = 6;
     public static final int INDICATION_TYPE_RESTING = 7;
     public static final int INDICATION_TYPE_USER_LOCKED = 8;
-    public static final int INDICATION_TYPE_NOW_PLAYING = 9;
     public static final int INDICATION_TYPE_REVERSE_CHARGING = 10;
 
     @IntDef({
@@ -317,7 +315,6 @@
             INDICATION_TYPE_TRUST,
             INDICATION_TYPE_RESTING,
             INDICATION_TYPE_USER_LOCKED,
-            INDICATION_TYPE_NOW_PLAYING,
             INDICATION_TYPE_REVERSE_CHARGING,
     })
     @Retention(RetentionPolicy.SOURCE)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 8659b8b..23c9408f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -64,7 +64,10 @@
     // Fade out faster than fade in to finish before QQS hides.
     private static final long QQS_FADE_OUT_DURATION = 50L;
 
-
+    /**
+     * List of all views that will be reset when clearing animation state
+     * see {@link #clearAnimationState()} }
+     */
     private final ArrayList<View> mAllViews = new ArrayList<>();
     /**
      * List of {@link View}s representing Quick Settings that are being animated from the quick QS
@@ -397,6 +400,7 @@
                     tileView.setClipChildren(true);
                     tileView.setClipToPadding(true);
                     firstPageBuilder.addFloat(tileView.getSecondaryLabel(), "alpha", 0, 1);
+                    mAllViews.add(tileView.getSecondaryLabel());
                 }
 
                 mAllViews.add(tileView);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index a34c6ba..8e43661 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -209,9 +209,17 @@
 
     protected int calculateContainerHeight() {
         int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
+        // Need to add the dragHandle height so touches will be intercepted by it.
+        int dragHandleHeight;
+        if (mDragHandle.getVisibility() == VISIBLE) {
+            dragHandleHeight = Math.round((1 - mQsExpansion) * mDragHandle.getHeight());
+        } else {
+            dragHandleHeight = 0;
+        }
         return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
                 : Math.round(mQsExpansion * (heightOverride - mHeader.getHeight()))
-                + mHeader.getHeight();
+                + mHeader.getHeight()
+                + dragHandleHeight;
     }
 
     int calculateContainerBottom() {
@@ -227,6 +235,7 @@
         mQsExpansion = expansion;
         mQSPanelContainer.setScrollingEnabled(expansion > 0f);
         mDragHandle.setAlpha(1.0f - expansion);
+        mDragHandle.setClickable(expansion == 0f); // Only clickable when fully collapsed
         updateExpansion();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 4242e1b..a1aff57 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -238,6 +238,11 @@
                     mQSPanelController.getMediaHost().getHostView().setAlpha(1.0f);
                     mQSAnimator.requestAnimatorUpdate();
                 });
+
+        mQsDragHandler.setOnClickListener(v -> {
+            Log.d(TAG, "drag handler clicked");
+            mCommandQueue.animateExpandSettingsPanel(null);
+        });
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 08da680..16b41a7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -303,7 +303,8 @@
             mInternetDialogSubTitle.setText(getSubtitleText());
         }
         updateEthernet();
-        setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular());
+        setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular()
+                || mInternetDialogController.isCarrierNetworkActive());
 
         if (!mCanConfigWifi) {
             return;
@@ -355,7 +356,7 @@
                 mInternetDialogController.hasEthernet() ? View.VISIBLE : View.GONE);
     }
 
-    private void setMobileDataLayout(boolean isCellularNetwork) {
+    private void setMobileDataLayout(boolean isCarrierNetworkConnected) {
         if (mInternetDialogController.isAirplaneModeEnabled()
                 || !mInternetDialogController.hasCarrier()) {
             mMobileNetworkLayout.setVisibility(View.GONE);
@@ -371,13 +372,13 @@
                 mMobileSummaryText.setVisibility(View.GONE);
             }
             mSignalIcon.setImageDrawable(getSignalStrengthDrawable());
-            mMobileTitleText.setTextAppearance(isCellularNetwork
+            mMobileTitleText.setTextAppearance(isCarrierNetworkConnected
                     ? R.style.TextAppearance_InternetDialog_Active
                     : R.style.TextAppearance_InternetDialog);
-            mMobileSummaryText.setTextAppearance(isCellularNetwork
+            mMobileSummaryText.setTextAppearance(isCarrierNetworkConnected
                     ? R.style.TextAppearance_InternetDialog_Secondary_Active
                     : R.style.TextAppearance_InternetDialog_Secondary);
-            mMobileNetworkLayout.setBackground(isCellularNetwork ? mBackgroundOn : null);
+            mMobileNetworkLayout.setBackground(isCarrierNetworkConnected ? mBackgroundOn : null);
 
             mMobileDataToggle.setVisibility(mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 95d3915..66d9c55 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -370,9 +370,12 @@
                 drawable = shared.get();
             }
 
-            drawable.setTint(activeNetworkIsCellular() ? mContext.getColor(
-                    R.color.connected_network_primary_color) : Utils.getColorAttrDefaultColor(
-                    mContext, android.R.attr.textColorTertiary));
+            int tintColor = Utils.getColorAttrDefaultColor(mContext,
+                    android.R.attr.textColorTertiary);
+            if (activeNetworkIsCellular() || isCarrierNetworkActive()) {
+                tintColor = mContext.getColor(R.color.connected_network_primary_color);
+            }
+            drawable.setTint(tintColor);
         } catch (Throwable e) {
             e.printStackTrace();
         }
@@ -533,9 +536,7 @@
         }
 
         int resId = mapIconSets(config).get(iconKey).dataContentDescription;
-        final MergedCarrierEntry mergedCarrierEntry =
-                mAccessPointController.getMergedCarrierEntry();
-        if (mergedCarrierEntry != null && mergedCarrierEntry.isDefaultNetwork()) {
+        if (isCarrierNetworkActive()) {
             SignalIcon.MobileIconGroup carrierMergedWifiIconGroup =
                     TelephonyIcons.CARRIER_MERGED_WIFI;
             resId = carrierMergedWifiIconGroup.dataContentDescription;
@@ -554,7 +555,7 @@
             return context.getString(R.string.mobile_data_no_connection);
         }
         String summary = networkTypeDescription;
-        if (activeNetworkIsCellular()) {
+        if (activeNetworkIsCellular() || isCarrierNetworkActive()) {
             summary = context.getString(R.string.preference_summary_default_combination,
                     context.getString(R.string.mobile_data_connection_active),
                     networkTypeDescription);
@@ -583,6 +584,12 @@
         }
     }
 
+    boolean isCarrierNetworkActive() {
+        final MergedCarrierEntry mergedCarrierEntry =
+                mAccessPointController.getMergedCarrierEntry();
+        return mergedCarrierEntry != null && mergedCarrierEntry.isDefaultNetwork();
+    }
+
     WifiManager getWifiManager() {
         return mWifiManager;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 2a8771e..7aa2dc7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -19,7 +19,6 @@
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
 import android.animation.ValueAnimator
-import android.app.WallpaperManager
 import android.os.SystemClock
 import android.os.Trace
 import android.util.IndentingPrintWriter
@@ -42,6 +41,7 @@
 import com.android.systemui.statusbar.phone.PanelExpansionListener
 import com.android.systemui.statusbar.phone.ScrimController
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.WallpaperController
 import java.io.FileDescriptor
 import java.io.PrintWriter
 import javax.inject.Inject
@@ -58,7 +58,7 @@
     private val biometricUnlockController: BiometricUnlockController,
     private val keyguardStateController: KeyguardStateController,
     private val choreographer: Choreographer,
-    private val wallpaperManager: WallpaperManager,
+    private val wallpaperController: WallpaperController,
     private val notificationShadeWindowController: NotificationShadeWindowController,
     private val dozeParameters: DozeParameters,
     dumpManager: DumpManager
@@ -215,15 +215,7 @@
         Trace.traceCounter(Trace.TRACE_TAG_APP, "shade_blur_radius", blur)
         blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur, opaque)
         lastAppliedBlur = blur
-        try {
-            if (root.isAttachedToWindow && root.windowToken != null) {
-                wallpaperManager.setWallpaperZoomOut(root.windowToken, zoomOut)
-            } else {
-                Log.i(TAG, "Won't set zoom. Window not attached $root")
-            }
-        } catch (e: IllegalArgumentException) {
-            Log.w(TAG, "Can't set zoom. Window is gone: ${root.windowToken}", e)
-        }
+        wallpaperController.setNotificationShadeZoom(zoomOut)
         listeners.forEach {
             it.onWallpaperZoomOutChanged(zoomOut)
             it.onBlurRadiusChanged(blur)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 71ecc17..865dbad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -228,7 +228,9 @@
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
+import com.android.systemui.unfold.UnfoldTransitionWallpaperController;
 import com.android.systemui.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.util.WallpaperController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.concurrency.MessageRouter;
 import com.android.systemui.volume.VolumeComponent;
@@ -537,7 +539,9 @@
     private final FeatureFlags mFeatureFlags;
     private final UnfoldTransitionConfig mUnfoldTransitionConfig;
     private final Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimation;
+    private final Lazy<UnfoldTransitionWallpaperController> mUnfoldWallpaperController;
     private final Lazy<StatusBarMoveFromCenterAnimationController> mMoveFromCenterAnimation;
+    private final WallpaperController mWallpaperController;
     private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
     private final MessageRouter mMessageRouter;
     private final WallpaperManager mWallpaperManager;
@@ -771,7 +775,9 @@
             BrightnessSlider.Factory brightnessSliderFactory,
             UnfoldTransitionConfig unfoldTransitionConfig,
             Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
+            Lazy<UnfoldTransitionWallpaperController> unfoldTransitionWallpaperController,
             Lazy<StatusBarMoveFromCenterAnimationController> statusBarUnfoldAnimationController,
+            WallpaperController wallpaperController,
             OngoingCallController ongoingCallController,
             SystemStatusAnimationScheduler animationScheduler,
             StatusBarLocationPublisher locationPublisher,
@@ -865,6 +871,8 @@
         mBrightnessSliderFactory = brightnessSliderFactory;
         mUnfoldTransitionConfig = unfoldTransitionConfig;
         mUnfoldLightRevealOverlayAnimation = unfoldLightRevealOverlayAnimation;
+        mUnfoldWallpaperController = unfoldTransitionWallpaperController;
+        mWallpaperController = wallpaperController;
         mMoveFromCenterAnimation = statusBarUnfoldAnimationController;
         mOngoingCallController = ongoingCallController;
         mAnimationScheduler = animationScheduler;
@@ -1052,6 +1060,7 @@
 
         if (mUnfoldTransitionConfig.isEnabled()) {
             mUnfoldLightRevealOverlayAnimation.get().init();
+            mUnfoldWallpaperController.get().init();
         }
 
         mPluginManager.addPluginListener(
@@ -1117,6 +1126,7 @@
         inflateStatusBarWindow();
         mNotificationShadeWindowViewController.setService(this, mNotificationShadeWindowController);
         mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener());
+        mWallpaperController.setRootView(mNotificationShadeWindowView);
 
         // TODO: Deal with the ugliness that comes from having some of the statusbar broken out
         // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
@@ -4294,6 +4304,8 @@
                 return;
             }
             WallpaperInfo info = mWallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
+            mWallpaperController.onWallpaperInfoUpdated(info);
+
             final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
                     com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
             // If WallpaperInfo is null, it must be ImageWallpaper.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index c45068e0..13eb75a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -107,7 +107,9 @@
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
+import com.android.systemui.unfold.UnfoldTransitionWallpaperController;
 import com.android.systemui.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.util.WallpaperController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.concurrency.MessageRouter;
 import com.android.systemui.volume.VolumeComponent;
@@ -216,7 +218,9 @@
             BrightnessSlider.Factory brightnessSliderFactory,
             UnfoldTransitionConfig unfoldTransitionConfig,
             Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
+            Lazy<UnfoldTransitionWallpaperController> unfoldTransitionWallpaperController,
             Lazy<StatusBarMoveFromCenterAnimationController> statusBarMoveFromCenterAnimation,
+            WallpaperController wallpaperController,
             OngoingCallController ongoingCallController,
             SystemStatusAnimationScheduler animationScheduler,
             StatusBarLocationPublisher locationPublisher,
@@ -312,7 +316,9 @@
                 brightnessSliderFactory,
                 unfoldTransitionConfig,
                 unfoldLightRevealOverlayAnimation,
+                unfoldTransitionWallpaperController,
                 statusBarMoveFromCenterAnimation,
+                wallpaperController,
                 ongoingCallController,
                 animationScheduler,
                 locationPublisher,
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionWallpaperController.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionWallpaperController.kt
new file mode 100644
index 0000000..8dd3d6b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionWallpaperController.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 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.unfold
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.util.WallpaperController
+import javax.inject.Inject
+
+@SysUISingleton
+class UnfoldTransitionWallpaperController @Inject constructor(
+    private val unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider,
+    private val wallpaperController: WallpaperController
+) {
+
+    fun init() {
+        unfoldTransitionProgressProvider.addCallback(TransitionListener())
+    }
+
+    private inner class TransitionListener : TransitionProgressListener {
+        override fun onTransitionProgress(progress: Float) {
+            wallpaperController.setUnfoldTransitionZoom(progress)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt b/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
new file mode 100644
index 0000000..db2aca8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 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.util
+
+import android.app.WallpaperInfo
+import android.app.WallpaperManager
+import android.util.Log
+import android.view.View
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlin.math.max
+
+private const val TAG = "WallpaperController"
+
+@SysUISingleton
+class WallpaperController @Inject constructor(private val wallpaperManager: WallpaperManager) {
+
+    var rootView: View? = null
+
+    private var notificationShadeZoomOut: Float = 0f
+    private var unfoldTransitionZoomOut: Float = 0f
+
+    private var wallpaperInfo: WallpaperInfo? = null
+
+    fun onWallpaperInfoUpdated(wallpaperInfo: WallpaperInfo?) {
+        this.wallpaperInfo = wallpaperInfo
+    }
+
+    private val shouldUseDefaultUnfoldTransition: Boolean
+        get() = wallpaperInfo?.shouldUseDefaultUnfoldTransition()
+            ?: true
+
+    fun setNotificationShadeZoom(zoomOut: Float) {
+        notificationShadeZoomOut = zoomOut
+        updateZoom()
+    }
+
+    fun setUnfoldTransitionZoom(zoomOut: Float) {
+        if (shouldUseDefaultUnfoldTransition) {
+            unfoldTransitionZoomOut = zoomOut
+            updateZoom()
+        }
+    }
+
+    private fun updateZoom() {
+        setWallpaperZoom(max(notificationShadeZoomOut, unfoldTransitionZoomOut))
+    }
+
+    private fun setWallpaperZoom(zoomOut: Float) {
+        try {
+            rootView?.let { root ->
+                if (root.isAttachedToWindow && root.windowToken != null) {
+                    wallpaperManager.setWallpaperZoomOut(root.windowToken, zoomOut)
+                } else {
+                    Log.i(TAG, "Won't set zoom. Window not attached $root")
+                }
+            }
+        } catch (e: IllegalArgumentException) {
+            Log.w(TAG, "Can't set zoom. Window is gone: ${rootView?.windowToken}", e)
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index 465370b..e5ae65f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar
 
-import android.app.WallpaperManager
 import android.os.IBinder
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
@@ -32,6 +31,7 @@
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.ScrimController
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.WallpaperController
 import com.android.systemui.util.mockito.eq
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -47,10 +47,8 @@
 import org.mockito.Mockito.anyFloat
 import org.mockito.Mockito.anyString
 import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.doThrow
 import org.mockito.Mockito.never
 import org.mockito.Mockito.reset
-import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.junit.MockitoJUnit
 import java.util.function.Consumer
@@ -65,7 +63,7 @@
     @Mock private lateinit var biometricUnlockController: BiometricUnlockController
     @Mock private lateinit var keyguardStateController: KeyguardStateController
     @Mock private lateinit var choreographer: Choreographer
-    @Mock private lateinit var wallpaperManager: WallpaperManager
+    @Mock private lateinit var wallpaperController: WallpaperController
     @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
     @Mock private lateinit var dumpManager: DumpManager
     @Mock private lateinit var root: View
@@ -101,7 +99,7 @@
 
         notificationShadeDepthController = NotificationShadeDepthController(
                 statusBarStateController, blurUtils, biometricUnlockController,
-                keyguardStateController, choreographer, wallpaperManager,
+                keyguardStateController, choreographer, wallpaperController,
                 notificationShadeWindowController, dozeParameters, dumpManager)
         notificationShadeDepthController.shadeAnimation = shadeAnimation
         notificationShadeDepthController.brightnessMirrorSpring = brightnessSpring
@@ -209,7 +207,7 @@
         notificationShadeDepthController.qsPanelExpansion = 0.25f
         notificationShadeDepthController.onPanelExpansionChanged(1f, tracking = false)
         notificationShadeDepthController.updateBlurCallback.doFrame(0)
-        verify(wallpaperManager).setWallpaperZoomOut(any(),
+        verify(wallpaperController).setNotificationShadeZoom(
                 eq(Interpolators.getNotificationScrimAlpha(0.25f, false /* notifications */)))
     }
 
@@ -242,14 +240,14 @@
         notificationShadeDepthController.transitionToFullShadeProgress = 1f
         notificationShadeDepthController.updateBlurCallback.doFrame(0)
         verify(blurUtils).applyBlur(any(), eq(0), eq(false))
-        verify(wallpaperManager).setWallpaperZoomOut(any(), eq(1f))
+        verify(wallpaperController).setNotificationShadeZoom(eq(1f))
     }
 
     @Test
     fun updateBlurCallback_setsBlurAndZoom() {
         notificationShadeDepthController.addListener(listener)
         notificationShadeDepthController.updateBlurCallback.doFrame(0)
-        verify(wallpaperManager).setWallpaperZoomOut(any(), anyFloat())
+        verify(wallpaperController).setNotificationShadeZoom(anyFloat())
         verify(listener).onWallpaperZoomOutChanged(anyFloat())
         verify(blurUtils).applyBlur(any(), anyInt(), eq(false))
     }
@@ -279,21 +277,6 @@
     }
 
     @Test
-    fun updateBlurCallback_invalidWindow() {
-        `when`(root.isAttachedToWindow).thenReturn(false)
-        notificationShadeDepthController.updateBlurCallback.doFrame(0)
-        verify(wallpaperManager, times(0)).setWallpaperZoomOut(any(), anyFloat())
-    }
-
-    @Test
-    fun updateBlurCallback_exception() {
-        doThrow(IllegalArgumentException("test exception")).`when`(wallpaperManager)
-                .setWallpaperZoomOut(any(), anyFloat())
-        notificationShadeDepthController.updateBlurCallback.doFrame(0)
-        verify(wallpaperManager).setWallpaperZoomOut(any(), anyFloat())
-    }
-
-    @Test
     fun ignoreShadeBlurUntilHidden_schedulesFrame() {
         notificationShadeDepthController.blursDisabledForAppLaunch = true
         verify(choreographer).postFrameCallback(
@@ -322,7 +305,7 @@
 
         notificationShadeDepthController.updateBlurCallback.doFrame(0)
         verify(notificationShadeWindowController).setBackgroundBlurRadius(eq(0))
-        verify(wallpaperManager).setWallpaperZoomOut(any(), eq(1f))
+        verify(wallpaperController).setNotificationShadeZoom(eq(1f))
         verify(blurUtils).applyBlur(eq(viewRootImpl), eq(0), eq(false))
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 751bc81..88a3827 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -140,7 +140,9 @@
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
+import com.android.systemui.unfold.UnfoldTransitionWallpaperController;
 import com.android.systemui.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.util.WallpaperController;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.concurrency.MessageRouterImpl;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -256,6 +258,8 @@
     @Mock private UnfoldTransitionConfig mUnfoldTransitionConfig;
     @Mock private Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimationLazy;
     @Mock private Lazy<StatusBarMoveFromCenterAnimationController> mMoveFromCenterAnimationLazy;
+    @Mock private Lazy<UnfoldTransitionWallpaperController> mUnfoldWallpaperController;
+    @Mock private WallpaperController mWallpaperController;
     @Mock private OngoingCallController mOngoingCallController;
     @Mock private SystemStatusAnimationScheduler mAnimationScheduler;
     @Mock private StatusBarLocationPublisher mLocationPublisher;
@@ -431,7 +435,9 @@
                 mBrightnessSliderFactory,
                 mUnfoldTransitionConfig,
                 mUnfoldLightRevealOverlayAnimationLazy,
+                mUnfoldWallpaperController,
                 mMoveFromCenterAnimationLazy,
+                mWallpaperController,
                 mOngoingCallController,
                 mAnimationScheduler,
                 mLocationPublisher,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
new file mode 100644
index 0000000..3cb19e3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2021 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.util
+
+import android.app.WallpaperInfo
+import android.app.WallpaperManager
+import android.os.IBinder
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.View
+import android.view.ViewRootImpl
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.eq
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.doThrow
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
+
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+@SmallTest
+class WallpaperControllerTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var wallpaperManager: WallpaperManager
+    @Mock
+    private lateinit var root: View
+    @Mock
+    private lateinit var viewRootImpl: ViewRootImpl
+    @Mock
+    private lateinit var windowToken: IBinder
+
+    @JvmField
+    @Rule
+    val mockitoRule = MockitoJUnit.rule()
+
+    private lateinit var wallaperController: WallpaperController
+
+    @Before
+    fun setup() {
+        `when`(root.viewRootImpl).thenReturn(viewRootImpl)
+        `when`(root.windowToken).thenReturn(windowToken)
+        `when`(root.isAttachedToWindow).thenReturn(true)
+
+        wallaperController = WallpaperController(wallpaperManager)
+
+        wallaperController.rootView = root
+    }
+
+    @Test
+    fun setNotificationShadeZoom_updatesWallpaperManagerZoom() {
+        wallaperController.setNotificationShadeZoom(0.5f)
+
+        verify(wallpaperManager).setWallpaperZoomOut(any(), eq(0.5f))
+    }
+
+    @Test
+    fun setUnfoldTransitionZoom_updatesWallpaperManagerZoom() {
+        wallaperController.setUnfoldTransitionZoom(0.5f)
+
+        verify(wallpaperManager).setWallpaperZoomOut(any(), eq(0.5f))
+    }
+
+    @Test
+    fun setUnfoldTransitionZoom_defaultUnfoldTransitionIsDisabled_doesNotUpdateWallpaperZoom() {
+        wallaperController.onWallpaperInfoUpdated(createWallpaperInfo(
+            useDefaultUnfoldTransition = false
+        ))
+
+        wallaperController.setUnfoldTransitionZoom(0.5f)
+
+        verify(wallpaperManager, never()).setWallpaperZoomOut(any(), anyFloat())
+    }
+
+    @Test
+    fun setUnfoldTransitionZoomAndNotificationShadeZoom_updatesWithMaximumZoom() {
+        wallaperController.setUnfoldTransitionZoom(0.7f)
+        clearInvocations(wallpaperManager)
+
+        wallaperController.setNotificationShadeZoom(0.5f)
+
+        verify(wallpaperManager).setWallpaperZoomOut(any(), eq(0.7f))
+    }
+
+    @Test
+    fun setNotificationShadeZoomAndThenUnfoldTransition_updatesWithMaximumZoom() {
+        wallaperController.setNotificationShadeZoom(0.7f)
+        clearInvocations(wallpaperManager)
+
+        wallaperController.setUnfoldTransitionZoom(0.5f)
+
+        verify(wallpaperManager).setWallpaperZoomOut(any(), eq(0.7f))
+    }
+
+    @Test
+    fun setNotificationZoom_invalidWindow_doesNotSetZoom() {
+        `when`(root.isAttachedToWindow).thenReturn(false)
+
+        verify(wallpaperManager, times(0)).setWallpaperZoomOut(any(), anyFloat())
+    }
+
+    @Test
+    fun setNotificationZoom_exceptionWhenUpdatingZoom_doesNotFail() {
+        doThrow(IllegalArgumentException("test exception")).`when`(wallpaperManager)
+            .setWallpaperZoomOut(any(), anyFloat())
+
+        wallaperController.setNotificationShadeZoom(0.5f)
+
+        verify(wallpaperManager).setWallpaperZoomOut(any(), anyFloat())
+    }
+
+    private fun createWallpaperInfo(useDefaultUnfoldTransition: Boolean = true): WallpaperInfo {
+        val info = mock(WallpaperInfo::class.java)
+        whenever(info.shouldUseDefaultUnfoldTransition()).thenReturn(useDefaultUnfoldTransition)
+        return info
+    }
+}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 3510501..cb1f744 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -221,6 +221,9 @@
     @GuardedBy("mLock")
     private final Set<Integer> mFuseMountedUser = new ArraySet<>();
 
+    @GuardedBy("mLock")
+    private final Set<Integer> mCeStoragePreparedUsers = new ArraySet<>();
+
     public static class Lifecycle extends SystemService {
         private StorageManagerService mStorageManagerService;
 
@@ -4854,5 +4857,19 @@
             }
             return primaryVolumeIds;
         }
+
+        @Override
+        public void markCeStoragePrepared(int userId) {
+            synchronized (mLock) {
+                mCeStoragePreparedUsers.add(userId);
+            }
+        }
+
+        @Override
+        public boolean isCeStoragePrepared(int userId) {
+            synchronized (mLock) {
+                return mCeStoragePreparedUsers.contains(userId);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 256c472..fa7eae3 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -594,8 +594,7 @@
 
             final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
             t.traceBegin("UM.onBeforeUnlockUser-" + userId);
-            final ArraySet<String> reconciledPackages =
-                    mInjector.getUserManager().onBeforeUnlockUser(userId);
+            mInjector.getUserManager().onBeforeUnlockUser(userId);
             t.traceEnd();
             synchronized (mLock) {
                 // Do not proceed if unexpected state
@@ -604,9 +603,6 @@
                 }
             }
             mInjector.getUserManagerInternal().setUserState(userId, uss.state);
-            t.traceBegin("UM.onUserStateRunningUnlocking-" + userId);
-            mInjector.getUserManager().onUserStateRunningUnlocking(userId, reconciledPackages);
-            t.traceEnd();
 
             uss.mUnlockProgress.setProgress(20);
 
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 18cb3ca..1c4b9ce 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -8443,6 +8443,20 @@
         mSpatializerHelper.setDesiredHeadTrackingMode(mode);
     }
 
+    /** @see Spatializer#setEffectParameter */
+    public void setSpatializerParameter(int key, @NonNull byte[] value) {
+        enforceModifyDefaultAudioEffectsPermission();
+        Objects.requireNonNull(value);
+        mSpatializerHelper.setEffectParameter(key, value);
+    }
+
+    /** @see Spatializer#getEffectParameter */
+    public void getSpatializerParameter(int key, @NonNull byte[] value) {
+        enforceModifyDefaultAudioEffectsPermission();
+        Objects.requireNonNull(value);
+        mSpatializerHelper.getEffectParameter(key, value);
+    }
+
     //==========================================================================================
     private boolean readCameraSoundForced() {
         return SystemProperties.getBoolean("audio.camerasound.force", false) ||
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 1d85974..ccaa96d 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -26,6 +26,7 @@
 import android.media.ISpatializer;
 import android.media.ISpatializerCallback;
 import android.media.ISpatializerHeadToSoundStagePoseCallback;
+import android.media.ISpatializerHeadTrackingCallback;
 import android.media.ISpatializerHeadTrackingModeCallback;
 import android.media.Spatializer;
 import android.media.SpatializerHeadTrackingMode;
@@ -71,6 +72,8 @@
     private int mDesiredHeadTrackingMode = Spatializer.HEAD_TRACKING_MODE_UNSUPPORTED;
     private @Nullable ISpatializer mSpat;
     private @Nullable SpatializerCallback mSpatCallback;
+    private @Nullable SpatializerHeadTrackingCallback mSpatHeadTrackingCallback;
+
 
     // default attributes and format that determine basic availability of spatialization
     private static final AudioAttributes DEFAULT_ATTRIBUTES = new AudioAttributes.Builder()
@@ -192,9 +195,13 @@
             }
             // TODO use reported spat level to change state
         }
+    };
 
+    // spatializer head tracking callback from native
+    private final class SpatializerHeadTrackingCallback
+            extends ISpatializerHeadTrackingCallback.Stub {
         public void onHeadTrackingModeChanged(byte mode)  {
-            logd("SpatializerCallback.onHeadTrackingModeChanged mode:" + mode);
+            logd("SpatializerHeadTrackingCallback.onHeadTrackingModeChanged mode:" + mode);
             int oldMode, newMode;
             synchronized (this) {
                 oldMode = mActualHeadTrackingMode;
@@ -208,12 +215,13 @@
 
         public void onHeadToSoundStagePoseUpdated(float[] headToStage)  {
             if (headToStage == null) {
-                Log.e(TAG, "SpatializerCallback.onHeadToStagePoseUpdated null transform");
+                Log.e(TAG, "SpatializerHeadTrackingCallback.onHeadToStagePoseUpdated"
+                        + "null transform");
                 return;
             }
             if (headToStage.length != 6) {
-                Log.e(TAG, "SpatializerCallback.onHeadToStagePoseUpdated invalid transform length"
-                        + headToStage.length);
+                Log.e(TAG, "SpatializerHeadTrackingCallback.onHeadToStagePoseUpdated"
+                        + " invalid transform length" + headToStage.length);
                 return;
             }
             if (DEBUG) {
@@ -222,7 +230,7 @@
                 for (float val : headToStage) {
                     t.append("[").append(String.format(Locale.ENGLISH, "%.3f", val)).append("]");
                 }
-                logd("SpatializerCallback.onHeadToStagePoseUpdated headToStage:" + t);
+                logd("SpatializerHeadTrackingCallback.onHeadToStagePoseUpdated headToStage:" + t);
             }
             dispatchPoseUpdate(headToStage);
         }
@@ -433,9 +441,14 @@
     private void createSpat() {
         if (mSpat == null) {
             mSpatCallback = new SpatializerCallback();
+            mSpatHeadTrackingCallback = new SpatializerHeadTrackingCallback();
             mSpat = AudioSystem.getSpatializer(mSpatCallback);
             try {
                 mSpat.setLevel((byte)  Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL);
+                //TODO: register heatracking callback only when sensors are registered
+                if (mSpat.isHeadTrackingSupported()) {
+                    mSpat.registerHeadTrackingCallback(mSpatHeadTrackingCallback);
+                }
             } catch (RemoteException e) {
                 Log.e(TAG, "Can't set spatializer level", e);
                 mState = STATE_NOT_SUPPORTED;
@@ -451,6 +464,7 @@
         if (mSpat != null) {
             mSpatCallback = null;
             try {
+                mSpat.registerHeadTrackingCallback(null);
                 mSpat.release();
                 mSpat = null;
             } catch (RemoteException e) {
@@ -728,4 +742,54 @@
         }
         mHeadPoseCallbacks.finishBroadcast();
     }
+
+    //------------------------------------------------------
+    // vendor parameters
+    synchronized void setEffectParameter(int key, @NonNull byte[] value) {
+        switch (mState) {
+            case STATE_UNINITIALIZED:
+            case STATE_NOT_SUPPORTED:
+                throw (new IllegalStateException(
+                        "Can't set parameter key:" + key + " without a spatializer"));
+            case STATE_ENABLED_UNAVAILABLE:
+            case STATE_DISABLED_UNAVAILABLE:
+            case STATE_DISABLED_AVAILABLE:
+            case STATE_ENABLED_AVAILABLE:
+                if (mSpat == null) {
+                    throw (new IllegalStateException(
+                            "null Spatializer for setParameter for key:" + key));
+                }
+                break;
+        }
+        // mSpat != null
+        try {
+            mSpat.setParameter(key, value);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error in setParameter for key:" + key, e);
+        }
+    }
+
+    synchronized void getEffectParameter(int key, @NonNull byte[] value) {
+        switch (mState) {
+            case STATE_UNINITIALIZED:
+            case STATE_NOT_SUPPORTED:
+                throw (new IllegalStateException(
+                        "Can't get parameter key:" + key + " without a spatializer"));
+            case STATE_ENABLED_UNAVAILABLE:
+            case STATE_DISABLED_UNAVAILABLE:
+            case STATE_DISABLED_AVAILABLE:
+            case STATE_ENABLED_AVAILABLE:
+                if (mSpat == null) {
+                    throw (new IllegalStateException(
+                            "null Spatializer for getParameter for key:" + key));
+                }
+                break;
+        }
+        // mSpat != null
+        try {
+            mSpat.getParameter(key, value);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error in getParameter for key:" + key, e);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 9c8ccd9..b5c8cd1 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -61,6 +61,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
@@ -71,6 +72,7 @@
 import com.android.server.SystemService;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -82,6 +84,8 @@
     private static final String SETTING_HIDL_DISABLED =
             "com.android.server.biometrics.AuthService.hidlDisabled";
     private static final int DEFAULT_HIDL_DISABLED = 0;
+    private static final String SYSPROP_FIRST_API_LEVEL = "ro.board.first_api_level";
+    private static final String SYSPROP_API_LEVEL = "ro.board.api_level";
 
     private final Injector mInjector;
 
@@ -624,7 +628,16 @@
 
         final SensorConfig[] hidlConfigs;
         if (!mInjector.isHidlDisabled(getContext())) {
-            final String[] configStrings = mInjector.getConfiguration(getContext());
+            final int firstApiLevel = SystemProperties.getInt(SYSPROP_FIRST_API_LEVEL, 0);
+            final int apiLevel = SystemProperties.getInt(SYSPROP_API_LEVEL, firstApiLevel);
+            String[] configStrings = mInjector.getConfiguration(getContext());
+            if (configStrings.length == 0 && apiLevel == Build.VERSION_CODES.R) {
+                // For backwards compatibility with R where biometrics could work without being
+                // configured in config_biometric_sensors. In the absence of a vendor provided
+                // configuration, we assume the weakest biometric strength (i.e. convenience).
+                Slog.w(TAG, "Found R vendor partition without config_biometric_sensors");
+                configStrings = generateRSdkCompatibleConfiguration();
+            }
             hidlConfigs = new SensorConfig[configStrings.length];
             for (int i = 0; i < configStrings.length; ++i) {
                 hidlConfigs[i] = new SensorConfig(configStrings[i]);
@@ -640,6 +653,31 @@
     }
 
     /**
+     * Generates an array of string configs with entries that correspond to the biometric features
+     * declared on the device. Returns an empty array if no biometric features are declared.
+     * Biometrics are assumed to be of the weakest strength class, i.e. convenience.
+     */
+    private @NonNull String[] generateRSdkCompatibleConfiguration() {
+        final PackageManager pm = getContext().getPackageManager();
+        final ArrayList<String> modalities = new ArrayList<>();
+        if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+            modalities.add(String.valueOf(BiometricAuthenticator.TYPE_FINGERPRINT));
+        }
+        if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
+            modalities.add(String.valueOf(BiometricAuthenticator.TYPE_FACE));
+        }
+        final String strength = String.valueOf(Authenticators.BIOMETRIC_CONVENIENCE);
+        final String[] configStrings = new String[modalities.size()];
+        for (int i = 0; i < modalities.size(); ++i) {
+            final String id = String.valueOf(i);
+            final String modality = modalities.get(i);
+            configStrings[i] = String.join(":" /* delimiter */, id, modality, strength);
+        }
+        Slog.d(TAG, "Generated config_biometric_sensors: " + Arrays.toString(configStrings));
+        return configStrings;
+    }
+
+    /**
      * Registers HIDL and AIDL authenticators for all of the available modalities.
      *
      * @param hidlSensors Array of {@link SensorConfig} configuration for all of the HIDL sensors
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 05e764b..6736d2a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -90,7 +90,7 @@
 
     private static final int MAX_DEDICATED_ADDRESS = 11;
 
-    private static final int MAX_HDMI_MESSAGE_HISTORY = 250;
+    private static final int INITIAL_HDMI_MESSAGE_HISTORY_SIZE = 250;
 
     private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
 
@@ -138,8 +138,10 @@
     private final HdmiControlService mService;
 
     // Stores recent CEC messages and HDMI Hotplug event history for debugging purpose.
-    private final ArrayBlockingQueue<Dumpable> mMessageHistory =
-            new ArrayBlockingQueue<>(MAX_HDMI_MESSAGE_HISTORY);
+    private ArrayBlockingQueue<Dumpable> mMessageHistory =
+            new ArrayBlockingQueue<>(INITIAL_HDMI_MESSAGE_HISTORY_SIZE);
+
+    private final Object mMessageHistoryLock = new Object();
 
     private final NativeWrapper mNativeWrapperImpl;
 
@@ -750,12 +752,39 @@
     }
 
     private void addEventToHistory(Dumpable event) {
-        if (!mMessageHistory.offer(event)) {
-            mMessageHistory.poll();
-            mMessageHistory.offer(event);
+        synchronized (mMessageHistoryLock) {
+            if (!mMessageHistory.offer(event)) {
+                mMessageHistory.poll();
+                mMessageHistory.offer(event);
+            }
         }
     }
 
+    int getMessageHistorySize() {
+        synchronized (mMessageHistoryLock) {
+            return mMessageHistory.size() + mMessageHistory.remainingCapacity();
+        }
+    }
+
+    boolean setMessageHistorySize(int newSize) {
+        if (newSize < INITIAL_HDMI_MESSAGE_HISTORY_SIZE) {
+            return false;
+        }
+        ArrayBlockingQueue<Dumpable> newMessageHistory = new ArrayBlockingQueue<>(newSize);
+
+        synchronized (mMessageHistoryLock) {
+            if (newSize < mMessageHistory.size()) {
+                for (int i = 0; i < mMessageHistory.size() - newSize; i++) {
+                    mMessageHistory.poll();
+                }
+            }
+
+            newMessageHistory.addAll(mMessageHistory);
+            mMessageHistory = newMessageHistory;
+        }
+        return true;
+    }
+
     void dump(final IndentingPrintWriter pw) {
         pw.println("CEC message history:");
         pw.increaseIndent();
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 6927094..6920c4b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -2366,6 +2366,25 @@
         }
 
         @Override
+        public boolean setMessageHistorySize(int newSize) {
+            enforceAccessPermission();
+            if (mCecController == null) {
+                return false;
+            }
+            return mCecController.setMessageHistorySize(newSize);
+        }
+
+        @Override
+        public int getMessageHistorySize() {
+            enforceAccessPermission();
+            if (mCecController != null) {
+                return mCecController.getMessageHistorySize();
+            } else {
+                return 0;
+            }
+        }
+
+        @Override
         public void addCecSettingChangeListener(String name,
                 final IHdmiCecSettingChangeListener listener) {
             enforceAccessPermission();
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
index a9b5214..8949427 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
@@ -95,6 +95,11 @@
         pw.println("  deviceselect <device id>");
         pw.println("      Switch to device with given id");
         pw.println("      The device's id is represented by its logical address.");
+        pw.println("  history_size get");
+        pw.println("      Gets the number of messages that can be stored in dumpsys history");
+        pw.println("  history_size set <new_size>");
+        pw.println("      Changes the number of messages that can be stored in dumpsys history to"
+                       + " new_size");
     }
 
     private int handleShellCommand(String cmd) throws RemoteException {
@@ -115,6 +120,8 @@
                 return setArcMode(pw);
             case "deviceselect":
                 return deviceSelect(pw);
+            case "history_size":
+                return historySize(pw);
         }
 
         getErrPrintWriter().println("Unhandled command: " + cmd);
@@ -275,6 +282,41 @@
         return 0;
     }
 
+    private int historySize(PrintWriter pw) throws RemoteException {
+        if (1 > getRemainingArgsCount()) {
+            throw new IllegalArgumentException("Use 'set' or 'get' for the command action");
+        }
+
+        String operation = getNextArgRequired();
+        switch (operation) {
+            case "get": {
+                int value = mBinderService.getMessageHistorySize();
+                pw.println("CEC dumpsys message history size = " + value);
+                return 0;
+            }
+            case "set": {
+                String arg = getNextArgRequired();
+                int value;
+                try {
+                    value = Integer.parseInt(arg);
+                } catch (NumberFormatException nfe) {
+                    pw.println("Cannot set CEC dumpsys message history size to " + arg);
+                    return 1;
+                }
+                if (mBinderService.setMessageHistorySize(value)) {
+                    pw.println("Setting CEC dumpsys message history size to " + value);
+                } else {
+                    pw.println(
+                            "Message history size not changed, was it lower than the minimum "
+                                    + "size?");
+                }
+                return 0;
+            }
+            default:
+                throw new IllegalArgumentException("Unknown operation: " + operation);
+        }
+    }
+
     private boolean receiveCallback(String command) {
         try {
             if (!mLatch.await(HdmiConfig.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index eb457c9..86d7dcd 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -3230,7 +3230,7 @@
      * Interface for the system to handle request from InputMonitors.
      */
     private final class InputMonitorHost extends IInputMonitorHost.Stub {
-        private IBinder mToken;
+        private final IBinder mToken;
 
         InputMonitorHost(IBinder token) {
             mToken = token;
@@ -3238,23 +3238,12 @@
 
         @Override
         public void pilferPointers() {
-            if (mToken == null) {
-                throw new IllegalStateException(
-                        "Illegal call to pilferPointers after InputMonitorHost is disposed.");
-            }
             nativePilferPointers(mPtr, mToken);
         }
 
         @Override
         public void dispose() {
-            // We do not remove the input monitor here by calling nativeRemoveInputChannel because
-            // it causes a race in InputDispatcher between the removal of the InputChannel through
-            // that call and the InputChannel#dispose call (which causes an FD hangup) from the
-            // client (b/189135695).
-            //
-            // NOTE: This means the client is responsible for properly closing the InputMonitor by
-            // disposing the InputChannel and all its duplicates.
-            mToken = null;
+            nativeRemoveInputChannel(mPtr, mToken);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e62102c..89cb7fe 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6957,7 +6957,7 @@
             }
             List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
                     UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
-                    true /* onlyCoreApps */, null);
+                    true /* onlyCoreApps */);
             mPrepareAppDataFuture = SystemServerInitThreadPool.submit(() -> {
                 TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync",
                         Trace.TRACE_TAG_PACKAGE_MANAGER);
@@ -15625,8 +15625,9 @@
         removeKeystoreDataIfNeeded(mInjector.getUserManagerInternal(), userId, appId);
 
         UserManagerInternal umInternal = mInjector.getUserManagerInternal();
+        StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class);
         final int flags;
-        if (umInternal.isUserUnlockingOrUnlocked(userId)) {
+        if (StorageManager.isUserKeyUnlocked(userId) && smInternal.isCeStoragePrepared(userId)) {
             flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
         } else if (umInternal.isUserRunning(userId)) {
             flags = StorageManager.FLAG_STORAGE_DE;
@@ -18586,32 +18587,22 @@
      * <p>
      * Verifies that directories exist and that ownership and labeling is
      * correct for all installed apps on all mounted volumes.
-     *
-     * @param reconciledPackages A set that will be populated with package names that have
-     *                           successfully had their data reconciled. Any package names already
-     *                           contained will be skipped. Because this must be mutable when
-     *                           non-null, it is typed {@link ArraySet} to prevent accidental
-     *                           usage of {@link Collections#emptySet()}. Null can be passed if the
-     *                           caller doesn't need this functionality.
      */
     @NonNull
-    void reconcileAppsData(int userId, int flags, boolean migrateAppsData,
-            @Nullable ArraySet<String> reconciledPackages) {
+    void reconcileAppsData(int userId, int flags, boolean migrateAppsData) {
         final StorageManager storage = mInjector.getSystemService(StorageManager.class);
         for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
             final String volumeUuid = vol.getFsUuid();
             synchronized (mInstallLock) {
-                reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppsData,
-                        reconciledPackages);
+                reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppsData);
             }
         }
     }
 
     @GuardedBy("mInstallLock")
     void reconcileAppsDataLI(String volumeUuid, int userId, int flags,
-            boolean migrateAppData, @Nullable ArraySet<String> reconciledPackages) {
-        reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppData, false /* onlyCoreApps */,
-                reconciledPackages);
+            boolean migrateAppData) {
+        reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppData, false /* onlyCoreApps */);
     }
 
     /**
@@ -18626,8 +18617,7 @@
      */
     @GuardedBy("mInstallLock")
     private List<String> reconcileAppsDataLI(String volumeUuid, int userId, int flags,
-            boolean migrateAppData, boolean onlyCoreApps,
-            @Nullable ArraySet<String> reconciledPackages) {
+            boolean migrateAppData, boolean onlyCoreApps) {
         Slog.v(TAG, "reconcileAppsData for " + volumeUuid + " u" + userId + " 0x"
                 + Integer.toHexString(flags) + " migrateAppData=" + migrateAppData);
         List<String> result = onlyCoreApps ? new ArrayList<>() : null;
@@ -18690,9 +18680,6 @@
         int preparedCount = 0;
         for (PackageSetting ps : packages) {
             final String packageName = ps.name;
-            if (reconciledPackages != null && reconciledPackages.contains(packageName)) {
-                continue;
-            }
             if (ps.pkg == null) {
                 Slog.w(TAG, "Odd, missing scanned package " + packageName);
                 // TODO: might be due to legacy ASEC apps; we should circle back
@@ -18708,10 +18695,6 @@
             if (ps.getInstalled(userId)) {
                 prepareAppDataAndMigrate(batch, ps.pkg, userId, flags, migrateAppData);
                 preparedCount++;
-
-                if (reconciledPackages != null) {
-                    reconciledPackages.add(packageName);
-                }
             }
         }
         executeBatchLI(batch);
@@ -18745,7 +18728,8 @@
         StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class);
         for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
             final int flags;
-            if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+            if (StorageManager.isUserKeyUnlocked(user.id)
+                    && smInternal.isCeStoragePrepared(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             } else if (umInternal.isUserRunning(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE;
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index e8dcfc7..a70df91 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -38,6 +38,7 @@
 import android.os.UserHandle;
 import android.os.storage.StorageEventListener;
 import android.os.storage.StorageManager;
+import android.os.storage.StorageManagerInternal;
 import android.os.storage.VolumeInfo;
 import android.text.TextUtils;
 import android.util.Log;
@@ -157,9 +158,12 @@
         // Reconcile app data for all started/unlocked users
         final StorageManager sm = mPm.mInjector.getSystemService(StorageManager.class);
         UserManagerInternal umInternal = mPm.mInjector.getUserManagerInternal();
+        StorageManagerInternal smInternal = mPm.mInjector.getLocalService(
+                StorageManagerInternal.class);
         for (UserInfo user : mPm.mUserManager.getUsers(false /* includeDying */)) {
             final int flags;
-            if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+            if (StorageManager.isUserKeyUnlocked(user.id)
+                    && smInternal.isCeStoragePrepared(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             } else if (umInternal.isUserRunning(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE;
@@ -170,8 +174,7 @@
             try {
                 sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, flags);
                 synchronized (mPm.mInstallLock) {
-                    mPm.reconcileAppsDataLI(volumeUuid, user.id, flags, true /* migrateAppData */,
-                            null);
+                    mPm.reconcileAppsDataLI(volumeUuid, user.id, flags, true /* migrateAppData */);
                 }
             } catch (IllegalStateException e) {
                 // Device was probably ejected, and we'll process that event momentarily
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 40e0526..d02d301 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -80,6 +80,7 @@
 import android.os.UserManager.EnforcingUser;
 import android.os.UserManager.QuietModeFlag;
 import android.os.storage.StorageManager;
+import android.os.storage.StorageManagerInternal;
 import android.provider.Settings;
 import android.security.GateKeeper;
 import android.service.gatekeeper.IGateKeeperService;
@@ -4805,7 +4806,7 @@
         mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
         t.traceEnd();
         t.traceBegin("reconcileAppsData");
-        mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE, migrateAppsData, null);
+        mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE, migrateAppsData);
         t.traceEnd();
 
         if (userId != UserHandle.USER_SYSTEM) {
@@ -4821,14 +4822,11 @@
     /**
      * Called right before a user is unlocked. This gives us a chance to prepare
      * app storage.
-     *
-     * @return set of packages that reconciled app data
      */
-    @NonNull public ArraySet<String> onBeforeUnlockUser(@UserIdInt int userId) {
+    public void onBeforeUnlockUser(@UserIdInt int userId) {
         UserInfo userInfo = getUserInfo(userId);
         if (userInfo == null) {
-            // PMS requires mutable set, so the API uses ArraySet to prevent Collections.emptySet()
-            return new ArraySet<>();
+            return;
         }
         final int userSerial = userInfo.serialNumber;
         // Migrate only if build fingerprints mismatch
@@ -4839,33 +4837,11 @@
         mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_CE);
         t.traceEnd();
 
-        final ArraySet<String> reconciledPackages = new ArraySet<>();
-        t.traceBegin("reconcileAppsDataFirstPass-" + userId);
-        mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE, migrateAppsData,
-                reconciledPackages);
-        t.traceEnd();
-        return reconciledPackages;
-    }
+        StorageManagerInternal smInternal = LocalServices.getService(StorageManagerInternal.class);
+        smInternal.markCeStoragePrepared(userId);
 
-    /**
-     * Called right after a user state is moved to {@link UserState#STATE_RUNNING_UNLOCKING}. This
-     * gives us a chance to reconcile app data for apps installed since
-     * {@link #onBeforeUnlockUser(int)} was called.
-     *
-     * @param previouslyReconciledPackages the result from {@link #onBeforeUnlockUser(int)}
-     */
-    public void onUserStateRunningUnlocking(@UserIdInt int userId,
-            @NonNull ArraySet<String> previouslyReconciledPackages) {
-        final UserInfo userInfo = getUserInfo(userId);
-        if (userInfo == null) {
-            return;
-        }
-        // Migrate only if build fingerprints mismatch
-        boolean migrateAppsData = !Build.FINGERPRINT.equals(userInfo.lastLoggedInFingerprint);
-        final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
-        t.traceBegin("reconcileAppsDataSecondPass-" + userId);
-        mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE, migrateAppsData,
-                previouslyReconciledPackages);
+        t.traceBegin("reconcileAppsData-" + userId);
+        mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE, migrateAppsData);
         t.traceEnd();
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3f205c9..84b10d0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -6548,7 +6548,8 @@
 
         @Override
         public PackageConfigurationUpdater createPackageConfigurationUpdater() {
-            return new PackageConfigurationUpdaterImpl(Binder.getCallingPid());
+            return new PackageConfigurationUpdaterImpl(Binder.getCallingPid(),
+                    ActivityTaskManagerService.this);
         }
 
         @Override
@@ -6565,57 +6566,4 @@
                     null /* trigger */, mRootWindowContainer.getDefaultDisplay());
         }
     }
-
-    final class PackageConfigurationUpdaterImpl implements
-            ActivityTaskManagerInternal.PackageConfigurationUpdater {
-        private final int mPid;
-        private Integer mNightMode;
-        private LocaleList mLocales;
-
-        PackageConfigurationUpdaterImpl(int pid) {
-            mPid = pid;
-        }
-
-        @Override
-        public ActivityTaskManagerInternal.PackageConfigurationUpdater setNightMode(int nightMode) {
-            mNightMode = nightMode;
-            return this;
-        }
-
-        @Override
-        public ActivityTaskManagerInternal.PackageConfigurationUpdater
-                setLocales(LocaleList locales) {
-            mLocales = locales;
-            return this;
-        }
-
-        @Override
-        public void commit() {
-            synchronized (mGlobalLock) {
-                final long ident = Binder.clearCallingIdentity();
-                try {
-                    final WindowProcessController wpc = mProcessMap.getProcess(mPid);
-                    if (wpc == null) {
-                        Slog.w(TAG, "Override application configuration: cannot find pid " + mPid);
-                        return;
-                    }
-                    LocaleList localesOverride = LocaleOverlayHelper.combineLocalesIfOverlayExists(
-                            mLocales, getGlobalConfiguration().getLocales());
-                    wpc.applyAppSpecificConfig(mNightMode, localesOverride);
-                    wpc.updateAppSpecificSettingsForAllActivities(mNightMode, localesOverride);
-                    mPackageConfigPersister.updateFromImpl(wpc.mName, wpc.mUserId, this);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-            }
-        }
-
-        Integer getNightMode() {
-            return mNightMode;
-        }
-
-        LocaleList getLocales() {
-            return mLocales;
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/wm/PackageConfigPersister.java b/services/core/java/com/android/server/wm/PackageConfigPersister.java
index 505c4be..52eea4d 100644
--- a/services/core/java/com/android/server/wm/PackageConfigPersister.java
+++ b/services/core/java/com/android/server/wm/PackageConfigPersister.java
@@ -173,7 +173,7 @@
 
     @GuardedBy("mLock")
     void updateFromImpl(String packageName, int userId,
-            ActivityTaskManagerService.PackageConfigurationUpdaterImpl impl) {
+            PackageConfigurationUpdaterImpl impl) {
         synchronized (mLock) {
             PackageConfigRecord record = findRecordOrCreate(mModified, packageName, userId);
             if (impl.getNightMode() != null) {
diff --git a/services/core/java/com/android/server/wm/PackageConfigurationUpdaterImpl.java b/services/core/java/com/android/server/wm/PackageConfigurationUpdaterImpl.java
new file mode 100644
index 0000000..96025054
--- /dev/null
+++ b/services/core/java/com/android/server/wm/PackageConfigurationUpdaterImpl.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 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.os.Binder;
+import android.os.LocaleList;
+import android.util.Slog;
+
+/**
+ * An implementation of {@link ActivityTaskManagerInternal.PackageConfigurationUpdater}.
+ */
+final class PackageConfigurationUpdaterImpl implements
+        ActivityTaskManagerInternal.PackageConfigurationUpdater {
+    private static final String TAG = "PackageConfigurationUpdaterImpl";
+    private final int mPid;
+    private Integer mNightMode;
+    private LocaleList mLocales;
+    private ActivityTaskManagerService mAtm;
+
+    PackageConfigurationUpdaterImpl(int pid, ActivityTaskManagerService atm) {
+        mPid = pid;
+        mAtm = atm;
+    }
+
+    @Override
+    public ActivityTaskManagerInternal.PackageConfigurationUpdater setNightMode(int nightMode) {
+        synchronized (this) {
+            mNightMode = nightMode;
+        }
+        return this;
+    }
+
+    @Override
+    public ActivityTaskManagerInternal.PackageConfigurationUpdater
+            setLocales(LocaleList locales) {
+        synchronized (this) {
+            mLocales = locales;
+        }
+        return this;
+    }
+
+    @Override
+    public void commit() {
+        synchronized (this) {
+            synchronized (mAtm.mGlobalLock) {
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    final WindowProcessController wpc = mAtm.mProcessMap.getProcess(mPid);
+                    if (wpc == null) {
+                        Slog.w(TAG, "Override application configuration: cannot find pid " + mPid);
+                        return;
+                    }
+                    LocaleList localesOverride = LocaleOverlayHelper.combineLocalesIfOverlayExists(
+                            mLocales, mAtm.getGlobalConfiguration().getLocales());
+                    wpc.applyAppSpecificConfig(mNightMode, localesOverride);
+                    wpc.updateAppSpecificSettingsForAllActivities(mNightMode, localesOverride);
+                    mAtm.mPackageConfigPersister.updateFromImpl(wpc.mName, wpc.mUserId, this);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+        }
+    }
+
+    Integer getNightMode() {
+        return mNightMode;
+    }
+
+    LocaleList getLocales() {
+        return mLocales;
+    }
+}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index be1502a..1ef04be 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -147,7 +147,12 @@
     }
 
     // Possible values for authentication types.
-    /** No authentication type. */
+    /**
+     * Authentication type is unknown.
+     * @hide
+     */
+    public static final int AUTH_TYPE_UNKNOWN = -1;
+    /** Authentication is not required. */
     public static final int AUTH_TYPE_NONE = 0;
     /** Authentication type for PAP. */
     public static final int AUTH_TYPE_PAP = 1;
@@ -357,6 +362,7 @@
 
     /** @hide */
     @IntDef(prefix = { "AUTH_TYPE_" }, value = {
+        AUTH_TYPE_UNKNOWN,
         AUTH_TYPE_NONE,
         AUTH_TYPE_PAP,
         AUTH_TYPE_CHAP,
@@ -498,7 +504,8 @@
     private final String mOperatorNumeric;
     private final int mProtocol;
     private final int mRoamingProtocol;
-    private final int mMtu;
+    private final int mMtuV4;
+    private final int mMtuV6;
 
     private final boolean mCarrierEnabled;
 
@@ -522,13 +529,25 @@
     private final int mSkip464Xlat;
 
     /**
-     * Returns the MTU size of the mobile interface to which the APN connected.
+     * Returns the MTU size of the IPv4 mobile interface to which the APN connected. Note this value
+     * is used only if MTU size is not provided in {@link DataCallResponse}.
      *
      * @return the MTU size of the APN
      * @hide
      */
-    public int getMtu() {
-        return mMtu;
+    public int getMtuV4() {
+        return mMtuV4;
+    }
+
+    /**
+     * Returns the MTU size of the IPv6 mobile interface to which the APN connected. Note this value
+     * is used only if MTU size is not provided in {@link DataCallResponse}.
+     *
+     * @return the MTU size of the APN
+     * @hide
+     */
+    public int getMtuV6() {
+        return mMtuV6;
     }
 
     /**
@@ -879,13 +898,18 @@
         this.mMmsProxyPort = builder.mMmsProxyPort;
         this.mUser = builder.mUser;
         this.mPassword = builder.mPassword;
-        this.mAuthType = builder.mAuthType;
+        this.mAuthType = (builder.mAuthType != AUTH_TYPE_UNKNOWN)
+                ? builder.mAuthType
+                : TextUtils.isEmpty(builder.mUser)
+                        ? AUTH_TYPE_NONE
+                        : AUTH_TYPE_PAP_OR_CHAP;
         this.mApnTypeBitmask = builder.mApnTypeBitmask;
         this.mId = builder.mId;
         this.mOperatorNumeric = builder.mOperatorNumeric;
         this.mProtocol = builder.mProtocol;
         this.mRoamingProtocol = builder.mRoamingProtocol;
-        this.mMtu = builder.mMtu;
+        this.mMtuV4 = builder.mMtuV4;
+        this.mMtuV6 = builder.mMtuV6;
         this.mCarrierEnabled = builder.mCarrierEnabled;
         this.mNetworkTypeBitmask = builder.mNetworkTypeBitmask;
         this.mProfileId = builder.mProfileId;
@@ -903,66 +927,6 @@
     /**
      * @hide
      */
-    public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
-            String apnName, String proxyAddress, int proxyPort, Uri mmsc,
-            String mmsProxyAddress, int mmsProxyPort, String user, String password,
-            int authType, int mApnTypeBitmask, int protocol, int roamingProtocol,
-            boolean carrierEnabled, int networkTypeBitmask, int profileId,
-            boolean modemCognitive, int maxConns, int waitTime, int maxConnsTime, int mtu,
-            int mvnoType, String mvnoMatchData, int apnSetId, int carrierId, int skip464xlat) {
-        return new Builder()
-            .setId(id)
-            .setOperatorNumeric(operatorNumeric)
-            .setEntryName(entryName)
-            .setApnName(apnName)
-            .setProxyAddress(proxyAddress)
-            .setProxyPort(proxyPort)
-            .setMmsc(mmsc)
-            .setMmsProxyAddress(mmsProxyAddress)
-            .setMmsProxyPort(mmsProxyPort)
-            .setUser(user)
-            .setPassword(password)
-            .setAuthType(authType)
-            .setApnTypeBitmask(mApnTypeBitmask)
-            .setProtocol(protocol)
-            .setRoamingProtocol(roamingProtocol)
-            .setCarrierEnabled(carrierEnabled)
-            .setNetworkTypeBitmask(networkTypeBitmask)
-            .setProfileId(profileId)
-            .setModemCognitive(modemCognitive)
-            .setMaxConns(maxConns)
-            .setWaitTime(waitTime)
-            .setMaxConnsTime(maxConnsTime)
-            .setMtu(mtu)
-            .setMvnoType(mvnoType)
-            .setMvnoMatchData(mvnoMatchData)
-            .setApnSetId(apnSetId)
-            .setCarrierId(carrierId)
-            .setSkip464Xlat(skip464xlat)
-            .buildWithoutCheck();
-    }
-
-    /**
-     * @hide
-     */
-    public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
-            String apnName, String proxyAddress, int proxyPort, Uri mmsc,
-            String mmsProxyAddress, int mmsProxyPort, String user, String password,
-            int authType, int mApnTypeBitmask, int protocol, int roamingProtocol,
-            boolean carrierEnabled, int networkTypeBitmask, int profileId, boolean modemCognitive,
-            int maxConns, int waitTime, int maxConnsTime, int mtu, int mvnoType,
-            String mvnoMatchData) {
-        return makeApnSetting(id, operatorNumeric, entryName, apnName, proxyAddress, proxyPort,
-            mmsc, mmsProxyAddress, mmsProxyPort, user, password, authType, mApnTypeBitmask,
-            protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, profileId,
-            modemCognitive, maxConns, waitTime, maxConnsTime, mtu, mvnoType, mvnoMatchData,
-            Carriers.NO_APN_SET_ID, TelephonyManager.UNKNOWN_CARRIER_ID,
-            Carriers.SKIP_464XLAT_DEFAULT);
-    }
-
-    /**
-     * @hide
-     */
     public static ApnSetting makeApnSetting(Cursor cursor) {
         final int apnTypesBitmask = getApnTypesBitmaskFromString(
                 cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
@@ -975,272 +939,99 @@
                 ServiceState.convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
         }
 
-        return makeApnSetting(
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
-            cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
-            portFromString(cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
-            UriFromString(cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
-            cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
-            portFromString(cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
-            apnTypesBitmask,
-            getProtocolIntFromString(
-                cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))),
-            getProtocolIntFromString(
-                cursor.getString(cursor.getColumnIndexOrThrow(
-                    Telephony.Carriers.ROAMING_PROTOCOL))),
-            cursor.getInt(cursor.getColumnIndexOrThrow(
-                Telephony.Carriers.CARRIER_ENABLED)) == 1,
-            networkTypeBitmask,
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(
-                Telephony.Carriers.MODEM_PERSIST)) == 1,
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNECTIONS)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME_RETRY)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(
-                Telephony.Carriers.TIME_LIMIT_FOR_MAX_CONNECTIONS)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
-            getMvnoTypeIntFromString(
-                cursor.getString(cursor.getColumnIndexOrThrow(
-                    Telephony.Carriers.MVNO_TYPE))),
-            cursor.getString(cursor.getColumnIndexOrThrow(
-                Telephony.Carriers.MVNO_MATCH_DATA)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.CARRIER_ID)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Carriers.SKIP_464XLAT)));
+        return new Builder()
+                .setId(cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)))
+                .setOperatorNumeric(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)))
+                .setEntryName(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)))
+                .setApnName(cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)))
+                .setProxyAddress(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)))
+                .setProxyPort(portFromString(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))))
+                .setMmsc(UriFromString(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))))
+                .setMmsProxyAddress(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)))
+                .setMmsProxyPort(portFromString(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))))
+                .setUser(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)))
+                .setPassword(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)))
+                .setAuthType(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)))
+                .setApnTypeBitmask(apnTypesBitmask)
+                .setProtocol(getProtocolIntFromString(
+                        cursor.getString(
+                                cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))))
+                .setRoamingProtocol(getProtocolIntFromString(
+                        cursor.getString(cursor.getColumnIndexOrThrow(
+                                Telephony.Carriers.ROAMING_PROTOCOL))))
+                .setCarrierEnabled(cursor.getInt(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.CARRIER_ENABLED)) == 1)
+                .setNetworkTypeBitmask(networkTypeBitmask)
+                .setProfileId(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)))
+                .setModemCognitive(cursor.getInt(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.MODEM_PERSIST)) == 1)
+                .setMaxConns(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNECTIONS)))
+                .setWaitTime(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME_RETRY)))
+                .setMaxConnsTime(cursor.getInt(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.TIME_LIMIT_FOR_MAX_CONNECTIONS)))
+                .setMtuV4(cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)))
+                .setMtuV6(UNSET_MTU) // TODO: Add corresponding support in telephony provider
+                .setMvnoType(getMvnoTypeIntFromString(
+                        cursor.getString(cursor.getColumnIndexOrThrow(
+                                Telephony.Carriers.MVNO_TYPE))))
+                .setMvnoMatchData(cursor.getString(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.MVNO_MATCH_DATA)))
+                .setApnSetId(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)))
+                .setCarrierId(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.CARRIER_ID)))
+                .setSkip464Xlat(cursor.getInt(cursor.getColumnIndexOrThrow(Carriers.SKIP_464XLAT)))
+                .buildWithoutCheck();
     }
 
     /**
      * @hide
      */
     public static ApnSetting makeApnSetting(ApnSetting apn) {
-        return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
-            apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
-            apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
-            apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
-            apn.mProfileId, apn.mPersistent, apn.mMaxConns, apn.mWaitTime,
-            apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId,
-            apn.mCarrierId, apn.mSkip464Xlat);
-    }
-
-    /**
-     * Creates an ApnSetting object from a string.
-     *
-     * @param data the string to read.
-     *
-     * The string must be in one of two formats (newlines added for clarity,
-     * spaces are optional):
-     *
-     * v1 format:
-     *   <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...],
-     *
-     * v2 format:
-     *   [ApnSettingV2] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *
-     * v3 format:
-     *   [ApnSettingV3] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>
-     *
-     * v4 format:
-     *   [ApnSettingV4] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>
-     *
-     * v5 format:
-     *   [ApnSettingV5] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>
-     *
-     * v6 format:
-     *   [ApnSettingV6] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>, <carrierId>
-     *
-     * v7 format:
-     *   [ApnSettingV7] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>, <carrierId>, <skip464xlat>
-     *
-     * Note that the strings generated by {@link #toString()} do not contain the username
-     * and password and thus cannot be read by this method.
-     *
-     * This method may return {@code null} if the input string is invalid.
-     *
-     * @hide
-     */
-    public static ApnSetting fromString(String data) {
-        if (data == null) return null;
-
-        int version;
-        // matches() operates on the whole string, so append .* to the regex.
-        if (data.matches(V7_FORMAT_REGEX + ".*")) {
-            version = 7;
-            data = data.replaceFirst(V7_FORMAT_REGEX, "");
-        } else if (data.matches(V6_FORMAT_REGEX + ".*")) {
-            version = 6;
-            data = data.replaceFirst(V6_FORMAT_REGEX, "");
-        } else if (data.matches(V5_FORMAT_REGEX + ".*")) {
-            version = 5;
-            data = data.replaceFirst(V5_FORMAT_REGEX, "");
-        } else if (data.matches(V4_FORMAT_REGEX + ".*")) {
-            version = 4;
-            data = data.replaceFirst(V4_FORMAT_REGEX, "");
-        } else if (data.matches(V3_FORMAT_REGEX + ".*")) {
-            version = 3;
-            data = data.replaceFirst(V3_FORMAT_REGEX, "");
-        } else if (data.matches(V2_FORMAT_REGEX + ".*")) {
-            version = 2;
-            data = data.replaceFirst(V2_FORMAT_REGEX, "");
-        } else {
-            version = 1;
-        }
-
-        String[] a = data.split("\\s*,\\s*", -1);
-        if (a.length < 14) {
-            return null;
-        }
-
-        int authType;
-        try {
-            authType = Integer.parseInt(a[12]);
-        } catch (NumberFormatException e) {
-            authType = 0;
-        }
-
-        String[] typeArray;
-        String protocol, roamingProtocol;
-        boolean carrierEnabled;
-        int bearerBitmask = 0;
-        int networkTypeBitmask = 0;
-        int profileId = 0;
-        boolean modemCognitive = false;
-        int maxConns = 0;
-        int waitTime = 0;
-        int maxConnsTime = 0;
-        int mtu = UNSET_MTU;
-        String mvnoType = "";
-        String mvnoMatchData = "";
-        int apnSetId = Carriers.NO_APN_SET_ID;
-        int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
-        int skip464xlat = Carriers.SKIP_464XLAT_DEFAULT;
-        if (version == 1) {
-            typeArray = new String[a.length - 13];
-            System.arraycopy(a, 13, typeArray, 0, a.length - 13);
-            protocol = PROTOCOL_INT_MAP.get(PROTOCOL_IP);
-            roamingProtocol = PROTOCOL_INT_MAP.get(PROTOCOL_IP);
-            carrierEnabled = true;
-        } else {
-            if (a.length < 18) {
-                return null;
-            }
-            typeArray = a[13].split("\\s*\\|\\s*");
-            protocol = a[14];
-            roamingProtocol = a[15];
-            carrierEnabled = Boolean.parseBoolean(a[16]);
-
-            bearerBitmask = ServiceState.getBitmaskFromString(a[17]);
-
-            if (a.length > 22) {
-                modemCognitive = Boolean.parseBoolean(a[19]);
-                try {
-                    profileId = Integer.parseInt(a[18]);
-                    maxConns = Integer.parseInt(a[20]);
-                    waitTime = Integer.parseInt(a[21]);
-                    maxConnsTime = Integer.parseInt(a[22]);
-                } catch (NumberFormatException e) {
-                }
-            }
-            if (a.length > 23) {
-                try {
-                    mtu = Integer.parseInt(a[23]);
-                } catch (NumberFormatException e) {
-                }
-            }
-            if (a.length > 25) {
-                mvnoType = a[24];
-                mvnoMatchData = a[25];
-            }
-            if (a.length > 26) {
-                networkTypeBitmask = ServiceState.getBitmaskFromString(a[26]);
-            }
-            if (a.length > 27) {
-                apnSetId = Integer.parseInt(a[27]);
-            }
-            if (a.length > 28) {
-                carrierId = Integer.parseInt(a[28]);
-            }
-            if (a.length > 29) {
-                try {
-                    skip464xlat = Integer.parseInt(a[29]);
-                } catch (NumberFormatException e) {
-                }
-            }
-        }
-
-        // If both bearerBitmask and networkTypeBitmask were specified, bearerBitmask would be
-        // ignored.
-        if (networkTypeBitmask == 0) {
-            networkTypeBitmask =
-                ServiceState.convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
-        }
-        return makeApnSetting(-1, a[10] + a[11], a[0], a[1], a[2],
-            portFromString(a[3]), UriFromString(a[7]), a[8],
-            portFromString(a[9]), a[4], a[5], authType,
-            getApnTypesBitmaskFromString(TextUtils.join(",", typeArray)),
-            getProtocolIntFromString(protocol), getProtocolIntFromString(roamingProtocol),
-            carrierEnabled, networkTypeBitmask, profileId, modemCognitive, maxConns, waitTime,
-            maxConnsTime, mtu, getMvnoTypeIntFromString(mvnoType), mvnoMatchData, apnSetId,
-            carrierId, skip464xlat);
-    }
-
-    /**
-     * Creates an array of ApnSetting objects from a string.
-     *
-     * @param data the string to read.
-     *
-     * Builds on top of the same format used by fromString, but allows for multiple entries
-     * separated by ";".
-     *
-     * @hide
-     */
-    public static List<ApnSetting> arrayFromString(String data) {
-        List<ApnSetting> retVal = new ArrayList<ApnSetting>();
-        if (TextUtils.isEmpty(data)) {
-            return retVal;
-        }
-        String[] apnStrings = data.split("\\s*;\\s*");
-        for (String apnString : apnStrings) {
-            ApnSetting apn = fromString(apnString);
-            if (apn != null) {
-                retVal.add(apn);
-            }
-        }
-        return retVal;
+        return new Builder()
+                .setId(apn.mId)
+                .setOperatorNumeric(apn.mOperatorNumeric)
+                .setEntryName(apn.mEntryName)
+                .setApnName(apn.mApnName)
+                .setProxyAddress(apn.mProxyAddress)
+                .setProxyPort(apn.mProxyPort)
+                .setMmsc(apn.mMmsc)
+                .setMmsProxyAddress(apn.mMmsProxyAddress)
+                .setMmsProxyPort(apn.mMmsProxyPort)
+                .setUser(apn.mUser)
+                .setPassword(apn.mPassword)
+                .setAuthType(apn.mAuthType)
+                .setApnTypeBitmask(apn.mApnTypeBitmask)
+                .setProtocol(apn.mProtocol)
+                .setRoamingProtocol(apn.mRoamingProtocol)
+                .setCarrierEnabled(apn.mCarrierEnabled)
+                .setNetworkTypeBitmask(apn.mNetworkTypeBitmask)
+                .setProfileId(apn.mProfileId)
+                .setModemCognitive(apn.mPersistent)
+                .setMaxConns(apn.mMaxConns)
+                .setWaitTime(apn.mWaitTime)
+                .setMaxConnsTime(apn.mMaxConnsTime)
+                .setMtuV4(apn.mMtuV4)
+                .setMtuV6(apn.mMtuV6)
+                .setMvnoType(apn.mMvnoType)
+                .setMvnoMatchData(apn.mMvnoMatchData)
+                .setApnSetId(apn.mApnSetId)
+                .setCarrierId(apn.mCarrierId)
+                .setSkip464Xlat(apn.mSkip464Xlat)
+                .buildWithoutCheck();
     }
 
     /**
@@ -1251,7 +1042,7 @@
      */
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("[ApnSettingV7] ")
+        sb.append("[ApnSetting] ")
                 .append(mEntryName)
                 .append(", ").append(mId)
                 .append(", ").append(mOperatorNumeric)
@@ -1272,7 +1063,8 @@
         sb.append(", ").append(mMaxConns);
         sb.append(", ").append(mWaitTime);
         sb.append(", ").append(mMaxConnsTime);
-        sb.append(", ").append(mMtu);
+        sb.append(", ").append(mMtuV4);
+        sb.append(", ").append(mMtuV6);
         sb.append(", ").append(MVNO_TYPE_INT_MAP.get(mMvnoType));
         sb.append(", ").append(mMvnoMatchData);
         sb.append(", ").append(mPermanentFailed);
@@ -1343,9 +1135,9 @@
     public int hashCode() {
         return Objects.hash(mApnName, mProxyAddress, mProxyPort, mMmsc, mMmsProxyAddress,
                 mMmsProxyPort, mUser, mPassword, mAuthType, mApnTypeBitmask, mId, mOperatorNumeric,
-                mProtocol, mRoamingProtocol, mMtu, mCarrierEnabled, mNetworkTypeBitmask, mProfileId,
-                mPersistent, mMaxConns, mWaitTime, mMaxConnsTime, mMvnoType, mMvnoMatchData,
-                mApnSetId, mCarrierId, mSkip464Xlat);
+                mProtocol, mRoamingProtocol, mMtuV4, mMtuV6, mCarrierEnabled, mNetworkTypeBitmask,
+                mProfileId, mPersistent, mMaxConns, mWaitTime, mMaxConnsTime, mMvnoType,
+                mMvnoMatchData, mApnSetId, mCarrierId, mSkip464Xlat);
     }
 
     @Override
@@ -1357,33 +1149,34 @@
         ApnSetting other = (ApnSetting) o;
 
         return mEntryName.equals(other.mEntryName)
-            && Objects.equals(mId, other.mId)
-            && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
-            && Objects.equals(mApnName, other.mApnName)
-            && Objects.equals(mProxyAddress, other.mProxyAddress)
-            && Objects.equals(mMmsc, other.mMmsc)
-            && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
-            && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
-            && Objects.equals(mProxyPort, other.mProxyPort)
-            && Objects.equals(mUser, other.mUser)
-            && Objects.equals(mPassword, other.mPassword)
-            && Objects.equals(mAuthType, other.mAuthType)
-            && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
-            && Objects.equals(mProtocol, other.mProtocol)
-            && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
-            && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
-            && Objects.equals(mProfileId, other.mProfileId)
-            && Objects.equals(mPersistent, other.mPersistent)
-            && Objects.equals(mMaxConns, other.mMaxConns)
-            && Objects.equals(mWaitTime, other.mWaitTime)
-            && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
-            && Objects.equals(mMtu, other.mMtu)
-            && Objects.equals(mMvnoType, other.mMvnoType)
-            && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
-            && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
-            && Objects.equals(mApnSetId, other.mApnSetId)
-            && Objects.equals(mCarrierId, other.mCarrierId)
-            && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
+                && Objects.equals(mId, other.mId)
+                && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+                && Objects.equals(mApnName, other.mApnName)
+                && Objects.equals(mProxyAddress, other.mProxyAddress)
+                && Objects.equals(mMmsc, other.mMmsc)
+                && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+                && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+                && Objects.equals(mProxyPort, other.mProxyPort)
+                && Objects.equals(mUser, other.mUser)
+                && Objects.equals(mPassword, other.mPassword)
+                && Objects.equals(mAuthType, other.mAuthType)
+                && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+                && Objects.equals(mProtocol, other.mProtocol)
+                && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
+                && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+                && Objects.equals(mProfileId, other.mProfileId)
+                && Objects.equals(mPersistent, other.mPersistent)
+                && Objects.equals(mMaxConns, other.mMaxConns)
+                && Objects.equals(mWaitTime, other.mWaitTime)
+                && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+                && Objects.equals(mMtuV4, other.mMtuV4)
+                && Objects.equals(mMtuV6, other.mMtuV6)
+                && Objects.equals(mMvnoType, other.mMvnoType)
+                && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+                && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+                && Objects.equals(mApnSetId, other.mApnSetId)
+                && Objects.equals(mCarrierId, other.mCarrierId)
+                && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
     }
 
     /**
@@ -1406,31 +1199,32 @@
         ApnSetting other = (ApnSetting) o;
 
         return mEntryName.equals(other.mEntryName)
-            && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
-            && Objects.equals(mApnName, other.mApnName)
-            && Objects.equals(mProxyAddress, other.mProxyAddress)
-            && Objects.equals(mMmsc, other.mMmsc)
-            && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
-            && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
-            && Objects.equals(mProxyPort, other.mProxyPort)
-            && Objects.equals(mUser, other.mUser)
-            && Objects.equals(mPassword, other.mPassword)
-            && Objects.equals(mAuthType, other.mAuthType)
-            && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
-            && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
-            && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
-            && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
-            && Objects.equals(mProfileId, other.mProfileId)
-            && Objects.equals(mPersistent, other.mPersistent)
-            && Objects.equals(mMaxConns, other.mMaxConns)
-            && Objects.equals(mWaitTime, other.mWaitTime)
-            && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
-            && Objects.equals(mMtu, other.mMtu)
-            && Objects.equals(mMvnoType, other.mMvnoType)
-            && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
-            && Objects.equals(mApnSetId, other.mApnSetId)
-            && Objects.equals(mCarrierId, other.mCarrierId)
-            && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
+                && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+                && Objects.equals(mApnName, other.mApnName)
+                && Objects.equals(mProxyAddress, other.mProxyAddress)
+                && Objects.equals(mMmsc, other.mMmsc)
+                && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+                && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+                && Objects.equals(mProxyPort, other.mProxyPort)
+                && Objects.equals(mUser, other.mUser)
+                && Objects.equals(mPassword, other.mPassword)
+                && Objects.equals(mAuthType, other.mAuthType)
+                && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+                && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
+                && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
+                && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+                && Objects.equals(mProfileId, other.mProfileId)
+                && Objects.equals(mPersistent, other.mPersistent)
+                && Objects.equals(mMaxConns, other.mMaxConns)
+                && Objects.equals(mWaitTime, other.mWaitTime)
+                && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+                && Objects.equals(mMtuV4, other.mMtuV4)
+                && Objects.equals(mMtuV6, other.mMtuV6)
+                && Objects.equals(mMvnoType, other.mMvnoType)
+                && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+                && Objects.equals(mApnSetId, other.mApnSetId)
+                && Objects.equals(mCarrierId, other.mCarrierId)
+                && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
     }
 
     /**
@@ -1732,7 +1526,7 @@
         dest.writeString(mApnName);
         dest.writeString(mProxyAddress);
         dest.writeInt(mProxyPort);
-        dest.writeValue(mMmsc);
+        dest.writeParcelable(mMmsc, flags);
         dest.writeString(mMmsProxyAddress);
         dest.writeInt(mMmsProxyPort);
         dest.writeString(mUser);
@@ -1742,40 +1536,53 @@
         dest.writeInt(mProtocol);
         dest.writeInt(mRoamingProtocol);
         dest.writeBoolean(mCarrierEnabled);
-        dest.writeInt(mMvnoType);
         dest.writeInt(mNetworkTypeBitmask);
+        dest.writeInt(mProfileId);
+        dest.writeBoolean(mPersistent);
+        dest.writeInt(mMaxConns);
+        dest.writeInt(mWaitTime);
+        dest.writeInt(mMaxConnsTime);
+        dest.writeInt(mMtuV4);
+        dest.writeInt(mMtuV6);
+        dest.writeInt(mMvnoType);
+        dest.writeString(mMvnoMatchData);
         dest.writeInt(mApnSetId);
         dest.writeInt(mCarrierId);
         dest.writeInt(mSkip464Xlat);
     }
 
     private static ApnSetting readFromParcel(Parcel in) {
-        final int id = in.readInt();
-        final String operatorNumeric = in.readString();
-        final String entryName = in.readString();
-        final String apnName = in.readString();
-        final String proxy = in.readString();
-        final int port = in.readInt();
-        final Uri mmsc = (Uri) in.readValue(Uri.class.getClassLoader());
-        final String mmsProxy = in.readString();
-        final int mmsPort = in.readInt();
-        final String user = in.readString();
-        final String password = in.readString();
-        final int authType = in.readInt();
-        final int apnTypesBitmask = in.readInt();
-        final int protocol = in.readInt();
-        final int roamingProtocol = in.readInt();
-        final boolean carrierEnabled = in.readBoolean();
-        final int mvnoType = in.readInt();
-        final int networkTypeBitmask = in.readInt();
-        final int apnSetId = in.readInt();
-        final int carrierId = in.readInt();
-        final int skip464xlat = in.readInt();
-
-        return makeApnSetting(id, operatorNumeric, entryName, apnName,
-                proxy, port, mmsc, mmsProxy, mmsPort, user, password, authType, apnTypesBitmask,
-                protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, 0, false,
-                0, 0, 0, 0, mvnoType, null, apnSetId, carrierId, skip464xlat);
+        return new Builder()
+                .setId(in.readInt())
+                .setOperatorNumeric(in.readString())
+                .setEntryName(in.readString())
+                .setApnName(in.readString())
+                .setProxyAddress(in.readString())
+                .setProxyPort(in.readInt())
+                .setMmsc(in.readParcelable(Uri.class.getClassLoader()))
+                .setMmsProxyAddress(in.readString())
+                .setMmsProxyPort(in.readInt())
+                .setUser(in.readString())
+                .setPassword(in.readString())
+                .setAuthType(in.readInt())
+                .setApnTypeBitmask(in.readInt())
+                .setProtocol(in.readInt())
+                .setRoamingProtocol(in.readInt())
+                .setCarrierEnabled(in.readBoolean())
+                .setNetworkTypeBitmask(in.readInt())
+                .setProfileId(in.readInt())
+                .setModemCognitive(in.readBoolean())
+                .setMaxConns(in.readInt())
+                .setWaitTime(in.readInt())
+                .setMaxConnsTime(in.readInt())
+                .setMtuV4(in.readInt())
+                .setMtuV6(in.readInt())
+                .setMvnoType(in.readInt())
+                .setMvnoMatchData(in.readString())
+                .setApnSetId(in.readInt())
+                .setCarrierId(in.readInt())
+                .setSkip464Xlat(in.readInt())
+                .buildWithoutCheck();
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<ApnSetting> CREATOR =
@@ -1834,13 +1641,14 @@
         private int mMmsProxyPort = UNSPECIFIED_INT;
         private String mUser;
         private String mPassword;
-        private int mAuthType;
+        private int mAuthType = AUTH_TYPE_UNKNOWN;
         private int mApnTypeBitmask;
         private int mId;
         private String mOperatorNumeric;
         private int mProtocol = UNSPECIFIED_INT;
         private int mRoamingProtocol = UNSPECIFIED_INT;
-        private int mMtu;
+        private int mMtuV4;
+        private int mMtuV6;
         private int mNetworkTypeBitmask;
         private boolean mCarrierEnabled;
         private int mProfileId;
@@ -1863,20 +1671,34 @@
          * Sets the unique database id for this entry.
          *
          * @param id the unique database id to set for this entry
+         * @hide
          */
-        private Builder setId(int id) {
+        public Builder setId(int id) {
             this.mId = id;
             return this;
         }
 
         /**
-         * Set the MTU size of the mobile interface to which the APN connected.
+         * Set the MTU size of the IPv4 mobile interface to which the APN connected. Note this value
+         * is used only if MTU size is not provided in {@link DataCallResponse}.
          *
-         * @param mtu the MTU size to set for the APN
+         * @param mtuV4 the MTU size to set for the APN
          * @hide
          */
-        public Builder setMtu(int mtu) {
-            this.mMtu = mtu;
+        public Builder setMtuV4(int mtuV4) {
+            this.mMtuV4 = mtuV4;
+            return this;
+        }
+
+        /**
+         * Set the MTU size of the IPv6 mobile interface to which the APN connected. Note this value
+         * is used only if MTU size is not provided in {@link DataCallResponse}.
+         *
+         * @param mtuV6 the MTU size to set for the APN
+         * @hide
+         */
+        public Builder setMtuV6(int mtuV6) {
+            this.mMtuV6 = mtuV6;
             return this;
         }
 
@@ -2237,7 +2059,8 @@
                     | TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX
                     | TYPE_XCAP | TYPE_VSIM | TYPE_BIP | TYPE_ENTERPRISE)) == 0
                 || TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
-                return null;
+                throw new IllegalArgumentException("mApName=" + mApnName + ", mEntryName="
+                        + mEntryName + ", mApnTypeBitmask=" + mApnTypeBitmask);
             }
             return new ApnSetting(this);
         }
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index f2a1249..93903d2 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -25,13 +25,11 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Annotation.ApnType;
+import android.telephony.TelephonyManager;
 import android.telephony.TelephonyManager.NetworkTypeBitMask;
 import android.telephony.data.ApnSetting.AuthType;
 import android.text.TextUtils;
 
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.util.TelephonyUtils;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
@@ -62,152 +60,141 @@
     /** 3GPP2 type data profile */
     public static final int TYPE_3GPP2 = 2;
 
-    private final int mProfileId;
+    private final @Type int mType;
 
-    private final String mApn;
+    private final @Nullable ApnSetting mApnSetting;
 
-    @ProtocolType
-    private final int mProtocolType;
-
-    @AuthType
-    private final int mAuthType;
-
-    private final String mUserName;
-
-    private final String mPassword;
-
-    @Type
-    private final int mType;
-
-    private final int mMaxConnectionsTime;
-
-    private final int mMaxConnections;
-
-    private final int mWaitTime;
-
-    private final boolean mEnabled;
-
-    @ApnType
-    private final int mSupportedApnTypesBitmask;
-
-    @ProtocolType
-    private final int mRoamingProtocolType;
-
-    @NetworkTypeBitMask
-    private final int mBearerBitmask;
-
-    private final int mMtuV4;
-
-    private final int mMtuV6;
-
-    private final boolean mPersistent;
+    private final @Nullable TrafficDescriptor mTrafficDescriptor;
 
     private final boolean mPreferred;
 
-    /** @hide */
-    private DataProfile(int profileId, String apn, @ProtocolType int protocolType, int authType,
-            String userName, String password, int type, int maxConnectionsTime,
-            int maxConnections, int waitTime, boolean enabled,
-            @ApnType int supportedApnTypesBitmask, @ProtocolType int roamingProtocolType,
-            @NetworkTypeBitMask int bearerBitmask, int mtuV4, int mtuV6, boolean persistent,
-            boolean preferred) {
-        this.mProfileId = profileId;
-        this.mApn = apn;
-        this.mProtocolType = protocolType;
-        if (authType == -1) {
-            authType = TextUtils.isEmpty(userName) ? RILConstants.SETUP_DATA_AUTH_NONE
-                    : RILConstants.SETUP_DATA_AUTH_PAP_CHAP;
+    private DataProfile(@NonNull Builder builder) {
+        mApnSetting = builder.mApnSetting;
+        mTrafficDescriptor = builder.mTrafficDescriptor;
+        mPreferred = builder.mPreferred;
+
+        if (builder.mType != -1) {
+            mType = builder.mType;
+        } else if (mApnSetting != null) {
+            int networkTypes = mApnSetting.getNetworkTypeBitmask();
+
+            if (networkTypes == 0) {
+                mType = DataProfile.TYPE_COMMON;
+            } else if ((networkTypes & TelephonyManager.NETWORK_STANDARDS_FAMILY_BITMASK_3GPP2)
+                    == networkTypes) {
+                mType = DataProfile.TYPE_3GPP2;
+            } else if ((networkTypes & TelephonyManager.NETWORK_STANDARDS_FAMILY_BITMASK_3GPP)
+                    == networkTypes) {
+                mType = DataProfile.TYPE_3GPP;
+            } else {
+                mType = DataProfile.TYPE_COMMON;
+            }
+        } else {
+            mType = DataProfile.TYPE_COMMON;
         }
-        this.mAuthType = authType;
-        this.mUserName = userName;
-        this.mPassword = password;
-        this.mType = type;
-        this.mMaxConnectionsTime = maxConnectionsTime;
-        this.mMaxConnections = maxConnections;
-        this.mWaitTime = waitTime;
-        this.mEnabled = enabled;
-        this.mSupportedApnTypesBitmask = supportedApnTypesBitmask;
-        this.mRoamingProtocolType = roamingProtocolType;
-        this.mBearerBitmask = bearerBitmask;
-        this.mMtuV4 = mtuV4;
-        this.mMtuV6 = mtuV6;
-        this.mPersistent = persistent;
-        this.mPreferred = preferred;
     }
 
     private DataProfile(Parcel source) {
-        mProfileId = source.readInt();
-        mApn = source.readString();
-        mProtocolType = source.readInt();
-        mAuthType = source.readInt();
-        mUserName = source.readString();
-        mPassword = source.readString();
         mType = source.readInt();
-        mMaxConnectionsTime = source.readInt();
-        mMaxConnections = source.readInt();
-        mWaitTime = source.readInt();
-        mEnabled = source.readBoolean();
-        mSupportedApnTypesBitmask = source.readInt();
-        mRoamingProtocolType = source.readInt();
-        mBearerBitmask = source.readInt();
-        mMtuV4 = source.readInt();
-        mMtuV6 = source.readInt();
-        mPersistent = source.readBoolean();
+        mApnSetting = source.readParcelable(ApnSetting.class.getClassLoader());
+        mTrafficDescriptor = source.readParcelable(TrafficDescriptor.class.getClassLoader());
         mPreferred = source.readBoolean();
     }
 
     /**
      * @return Id of the data profile.
      */
-    public int getProfileId() { return mProfileId; }
+    public int getProfileId() {
+        if (mApnSetting != null) {
+            return mApnSetting.getProfileId();
+        }
+        return 0;
+    }
 
     /**
      * @return The APN (Access Point Name) to establish data connection. This is a string
      * specifically defined by the carrier.
      */
     @NonNull
-    public String getApn() { return mApn; }
+    public String getApn() {
+        if (mApnSetting != null) {
+            return TextUtils.emptyIfNull(mApnSetting.getApnName());
+        }
+        return "";
+    }
 
     /**
      * @return The connection protocol defined in 3GPP TS 27.007 section 10.1.1.
      */
-    public @ProtocolType int getProtocolType() { return mProtocolType; }
+    public @ProtocolType int getProtocolType() {
+        if (mApnSetting != null) {
+            return mApnSetting.getProtocol();
+        }
+        return ApnSetting.PROTOCOL_IP;
+    }
 
     /**
      * @return The authentication protocol used for this PDP context.
      */
-    public @AuthType int getAuthType() { return mAuthType; }
+    public @AuthType int getAuthType() {
+        if (mApnSetting != null) {
+            return mApnSetting.getAuthType();
+        }
+        return ApnSetting.AUTH_TYPE_NONE;
+    }
 
     /**
      * @return The username for APN. Can be null.
      */
     @Nullable
-    public String getUserName() { return mUserName; }
+    public String getUserName() {
+        if (mApnSetting != null) {
+            return mApnSetting.getUser();
+        }
+        return null;
+    }
 
     /**
      * @return The password for APN. Can be null.
      */
     @Nullable
-    public String getPassword() { return mPassword; }
+    public String getPassword() {
+        if (mApnSetting != null) {
+            return mApnSetting.getPassword();
+        }
+        return null;
+    }
 
     /**
      * @return The profile type.
      */
-    public @Type int getType() { return mType; }
+    public @Type int getType() {
+        return mType;
+    }
 
     /**
      * @return The period in seconds to limit the maximum connections.
      *
      * @hide
      */
-    public int getMaxConnectionsTime() { return mMaxConnectionsTime; }
+    public int getMaxConnectionsTime() {
+        if (mApnSetting != null) {
+            return mApnSetting.getMaxConnsTime();
+        }
+        return 0;
+    }
 
     /**
      * @return The maximum connections allowed.
      *
      * @hide
      */
-    public int getMaxConnections() { return mMaxConnections; }
+    public int getMaxConnections() {
+        if (mApnSetting != null) {
+            return mApnSetting.getMaxConns();
+        }
+        return 0;
+    }
 
     /**
      * @return The required wait time in seconds after a successful UE initiated disconnect of a
@@ -216,57 +203,117 @@
      *
      * @hide
      */
-    public int getWaitTime() { return mWaitTime; }
+    public int getWaitTime() {
+        if (mApnSetting != null) {
+            return mApnSetting.getWaitTime();
+        }
+        return 0;
+    }
 
     /**
      * @return True if the profile is enabled.
      */
-    public boolean isEnabled() { return mEnabled; }
+    public boolean isEnabled() {
+        if (mApnSetting != null) {
+            return mApnSetting.isEnabled();
+        }
+        return false;
+    }
 
     /**
      * @return The supported APN types bitmask.
      */
-    public @ApnType int getSupportedApnTypesBitmask() { return mSupportedApnTypesBitmask; }
+    public @ApnType int getSupportedApnTypesBitmask() {
+        if (mApnSetting != null) {
+            return mApnSetting.getApnTypeBitmask();
+        }
+        return ApnSetting.TYPE_NONE;
+    }
 
     /**
      * @return The connection protocol on roaming network defined in 3GPP TS 27.007 section 10.1.1.
      */
-    public @ProtocolType int getRoamingProtocolType() { return mRoamingProtocolType; }
+    public @ProtocolType int getRoamingProtocolType() {
+        if (mApnSetting != null) {
+            return mApnSetting.getRoamingProtocol();
+        }
+        return ApnSetting.PROTOCOL_IP;
+    }
 
     /**
      * @return The bearer bitmask indicating the applicable networks for this data profile.
      */
-    public @NetworkTypeBitMask int getBearerBitmask() { return mBearerBitmask; }
+    public @NetworkTypeBitMask int getBearerBitmask() {
+        if (mApnSetting != null) {
+            return mApnSetting.getNetworkTypeBitmask();
+        }
+        return (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN;
+    }
 
     /**
      * @return The maximum transmission unit (MTU) size in bytes.
      * @deprecated use {@link #getMtuV4} or {@link #getMtuV6} instead.
      */
     @Deprecated
-    public int getMtu() { return mMtuV4; }
+    public int getMtu() {
+        return getMtuV4();
+    }
 
     /**
      * This replaces the deprecated method getMtu.
      * @return The maximum transmission unit (MTU) size in bytes, for IPv4.
      */
-    public int getMtuV4() { return mMtuV4; }
+    public int getMtuV4() {
+        if (mApnSetting != null) {
+            return mApnSetting.getMtuV4();
+        }
+        return 0;
+    }
 
     /**
      * @return The maximum transmission unit (MTU) size in bytes, for IPv6.
      */
-    public int getMtuV6() { return mMtuV6; }
+    public int getMtuV6() {
+        if (mApnSetting != null) {
+            return mApnSetting.getMtuV6();
+        }
+        return 0;
+    }
 
     /**
      * @return {@code true} if modem must persist this data profile.
      */
-    public boolean isPersistent() { return mPersistent; }
+    public boolean isPersistent() {
+        if (mApnSetting != null) {
+            return mApnSetting.isPersistent();
+        }
+        return false;
+    }
 
     /**
      * @return {@code true} if this data profile was used to bring up the last default
      * (i.e internet) data connection successfully, or the one chosen by the user in Settings'
      * APN editor. For one carrier there can be only one profiled preferred.
      */
-    public boolean isPreferred() { return  mPreferred; }
+    public boolean isPreferred() {
+        return mPreferred;
+    }
+
+    /**
+     * @return The APN setting
+     * @hide TODO: Remove before T is released.
+     */
+    public @Nullable ApnSetting getApnSetting() {
+        return mApnSetting;
+    }
+
+    /**
+     * @return The traffic descriptor
+     * @hide TODO: Remove before T is released.
+     */
+    public @Nullable TrafficDescriptor getTrafficDescriptor() {
+        return mTrafficDescriptor;
+    }
 
     @Override
     public int describeContents() {
@@ -276,34 +323,15 @@
     @NonNull
     @Override
     public String toString() {
-        return "DataProfile=" + mProfileId + "/" + mProtocolType + "/" + mAuthType
-                + "/" + (TelephonyUtils.IS_USER ? "***/***/***" :
-                         (mApn + "/" + mUserName + "/" + mPassword)) + "/" + mType + "/"
-                + mMaxConnectionsTime + "/" + mMaxConnections + "/"
-                + mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmask + "/"
-                + mRoamingProtocolType + "/" + mBearerBitmask + "/" + mMtuV4 + "/" + mMtuV6 + "/"
-                + mPersistent + "/" + mPreferred;
+        return "DataProfile=" + mApnSetting + ", " + mTrafficDescriptor + ", preferred="
+                + mPreferred;
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mProfileId);
-        dest.writeString(mApn);
-        dest.writeInt(mProtocolType);
-        dest.writeInt(mAuthType);
-        dest.writeString(mUserName);
-        dest.writeString(mPassword);
         dest.writeInt(mType);
-        dest.writeInt(mMaxConnectionsTime);
-        dest.writeInt(mMaxConnections);
-        dest.writeInt(mWaitTime);
-        dest.writeBoolean(mEnabled);
-        dest.writeInt(mSupportedApnTypesBitmask);
-        dest.writeInt(mRoamingProtocolType);
-        dest.writeInt(mBearerBitmask);
-        dest.writeInt(mMtuV4);
-        dest.writeInt(mMtuV6);
-        dest.writeBoolean(mPersistent);
+        dest.writeParcelable(mApnSetting, flags);
+        dest.writeParcelable(mTrafficDescriptor, flags);
         dest.writeBoolean(mPreferred);
     }
 
@@ -321,36 +349,18 @@
     };
 
     @Override
-    public boolean equals(@Nullable Object o) {
+    public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         DataProfile that = (DataProfile) o;
-        return mProfileId == that.mProfileId
-                && mProtocolType == that.mProtocolType
-                && mAuthType == that.mAuthType
-                && mType == that.mType
-                && mMaxConnectionsTime == that.mMaxConnectionsTime
-                && mMaxConnections == that.mMaxConnections
-                && mWaitTime == that.mWaitTime
-                && mEnabled == that.mEnabled
-                && mSupportedApnTypesBitmask == that.mSupportedApnTypesBitmask
-                && mRoamingProtocolType == that.mRoamingProtocolType
-                && mBearerBitmask == that.mBearerBitmask
-                && mMtuV4 == that.mMtuV4
-                && mMtuV6 == that.mMtuV6
-                && mPersistent == that.mPersistent
-                && mPreferred == that.mPreferred
-                && Objects.equals(mApn, that.mApn)
-                && Objects.equals(mUserName, that.mUserName)
-                && Objects.equals(mPassword, that.mPassword);
+        return mType == that.mType
+                && Objects.equals(mApnSetting, that.mApnSetting)
+                && Objects.equals(mTrafficDescriptor, that.mTrafficDescriptor);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword, mType,
-                mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled,
-                mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6,
-                mPersistent, mPreferred);
+        return Objects.hash(mType, mApnSetting, mTrafficDescriptor);
     }
 
     /**
@@ -383,13 +393,7 @@
         private String mPassword;
 
         @Type
-        private int mType;
-
-        private int mMaxConnectionsTime;
-
-        private int mMaxConnections;
-
-        private int mWaitTime;
+        private int mType = -1;
 
         private boolean mEnabled;
 
@@ -410,6 +414,10 @@
 
         private boolean mPreferred;
 
+        private ApnSetting mApnSetting;
+
+        private TrafficDescriptor mTrafficDescriptor;
+
         /**
          * Default constructor for Builder.
          */
@@ -496,48 +504,6 @@
         }
 
         /**
-         * Set the period in seconds to limit the maximum connections.
-         *
-         * @param maxConnectionsTime The profile type
-         * @return The same instance of the builder.
-         *
-         * @hide
-         */
-        public @NonNull Builder setMaxConnectionsTime(int maxConnectionsTime) {
-            mMaxConnectionsTime = maxConnectionsTime;
-            return this;
-        }
-
-        /**
-         * Set the maximum connections allowed.
-         *
-         * @param maxConnections The maximum connections allowed.
-         * @return The same instance of the builder.
-         *
-         * @hide
-         */
-        public @NonNull Builder setMaxConnections(int maxConnections) {
-            mMaxConnections = maxConnections;
-            return this;
-        }
-
-        /**
-         * Set the period in seconds to limit the maximum connections.
-         *
-         * @param waitTime The required wait time in seconds after a successful UE initiated
-         * disconnect of a given PDN connection before the device can send a new PDN connection
-         * request for that given PDN.
-         *
-         * @return The same instance of the builder.
-         *
-         * @hide
-         */
-        public @NonNull Builder setWaitTime(int waitTime) {
-            mWaitTime = waitTime;
-            return this;
-        }
-
-        /**
          * Enable the data profile
          *
          * @param isEnabled {@code true} to enable the data profile, otherwise disable.
@@ -587,8 +553,9 @@
          *
          * @param mtu The maximum transmission unit (MTU) size in bytes.
          * @return The same instance of the builder.
-         * @deprecated use {@link #setMtuV4} or {@link #setMtuV6} instead.
+         * @deprecated use {@link #setApnSetting(ApnSetting)} instead.
          */
+        @Deprecated
         public @NonNull Builder setMtu(int mtu) {
             mMtuV4 = mMtuV6 = mtu;
             return this;
@@ -631,7 +598,7 @@
         }
 
         /**
-         * Set data profile as persistent/non-persistent
+         * Set data profile as persistent/non-persistent.
          *
          * @param isPersistent {@code true} if this data profile was used to bring up the last
          * default (i.e internet) data connection successfully.
@@ -643,15 +610,63 @@
         }
 
         /**
+         * Set APN setting.
+         *
+         * @param apnSetting APN setting
+         * @return The same instance of the builder
+         *
+         * @hide // TODO: Remove before T is released.
+         */
+        public @NonNull Builder setApnSetting(@NonNull ApnSetting apnSetting) {
+            mApnSetting = apnSetting;
+            return this;
+        }
+
+        /**
+         * Set traffic descriptor.
+         *
+         * @param trafficDescriptor Traffic descriptor
+         * @return The same instance of the builder
+         *
+         * @hide // TODO: Remove before T is released.
+         */
+        public @NonNull Builder setTrafficDescriptor(@NonNull TrafficDescriptor trafficDescriptor) {
+            mTrafficDescriptor = trafficDescriptor;
+            return this;
+        }
+
+        /**
          * Build the DataProfile object
          *
          * @return The data profile object
          */
         public @NonNull DataProfile build() {
-            return new DataProfile(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword,
-                    mType, mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled,
-                    mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6,
-                    mPersistent, mPreferred);
+            if (mApnSetting == null && mApn != null) {
+                // This is for backwards compatibility.
+                mApnSetting = new ApnSetting.Builder()
+                        .setEntryName(mApn)
+                        .setApnName(mApn)
+                        .setApnTypeBitmask(mSupportedApnTypesBitmask)
+                        .setAuthType(mAuthType)
+                        .setCarrierEnabled(mEnabled)
+                        .setModemCognitive(mPersistent)
+                        .setMtuV4(mMtuV4)
+                        .setMtuV6(mMtuV6)
+                        .setNetworkTypeBitmask(mBearerBitmask)
+                        .setProfileId(mProfileId)
+                        .setPassword(mPassword)
+                        .setProtocol(mProtocolType)
+                        .setRoamingProtocol(mRoamingProtocolType)
+                        .setUser(mUserName)
+                        .build();
+            }
+
+            if (mApnSetting == null && mTrafficDescriptor == null) {
+                throw new IllegalArgumentException("APN setting and traffic descriptor can't be "
+                        + "both null.");
+            }
+
+            return new DataProfile(this);
         }
     }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index c17c823..64cb790 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -23,12 +23,20 @@
 val LAUNCHER_COMPONENT = FlickerComponentName("com.google.android.apps.nexuslauncher",
         "com.google.android.apps.nexuslauncher.NexusLauncherActivity")
 
+/**
+ * Checks that [FlickerComponentName.STATUS_BAR] window is visible and above the app windows in
+ * all WM trace entries
+ */
 fun FlickerTestParameter.statusBarWindowIsVisible() {
     assertWm {
         this.isAboveAppWindowVisible(FlickerComponentName.STATUS_BAR)
     }
 }
 
+/**
+ * Checks that [FlickerComponentName.NAV_BAR] window is visible and above the app windows in
+ * all WM trace entries
+ */
 fun FlickerTestParameter.navBarWindowIsVisible() {
     assertWm {
         this.isAboveAppWindowVisible(FlickerComponentName.NAV_BAR)
@@ -68,6 +76,10 @@
     }
 }
 
+/**
+ * Checks that [FlickerComponentName.NAV_BAR] layer is visible at the start and end of the SF
+ * trace
+ */
 fun FlickerTestParameter.navBarLayerIsVisible() {
     assertLayersStart {
         this.isVisible(FlickerComponentName.NAV_BAR)
@@ -77,6 +89,10 @@
     }
 }
 
+/**
+ * Checks that [FlickerComponentName.STATUS_BAR] layer is visible at the start and end of the SF
+ * trace
+ */
 fun FlickerTestParameter.statusBarLayerIsVisible() {
     assertLayersStart {
         this.isVisible(FlickerComponentName.STATUS_BAR)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index 22bf57a..9b34853 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -33,7 +33,32 @@
 
 /**
  * Test app closes by pressing back button
+ *
  * To run this test: `atest FlickerTests:CloseAppBackButtonTest`
+ *
+ * Actions:
+ *     Make sure no apps are running on the device
+ *     Launch an app [testApp] and wait animation to complete
+ *     Press back button
+ *
+ * To run only the presubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
+ *
+ * To run only the postsubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
+ *
+ * To run only the flaky assertions add: `--
+ *      --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
+ *
+ * Notes:
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [CloseAppTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
@@ -50,14 +75,23 @@
             }
         }
 
+    /** {@inheritDoc} */
     @FlakyTest
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
+    /** {@inheritDoc} */
     @Postsubmit
+    @Test
     override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
 
     companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+         * repetitions, screen orientation and navigation modes.
+         */
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun getParams(): List<FlickerTestParameter> {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index a1c0e01..e380794 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -31,8 +31,33 @@
 import org.junit.runners.Parameterized
 
 /**
- * Test app closes by pressing home button.
+ * Test app closes by pressing home button
+ *
  * To run this test: `atest FlickerTests:CloseAppHomeButtonTest`
+ *
+ * Actions:
+ *     Make sure no apps are running on the device
+ *     Launch an app [testApp] and wait animation to complete
+ *     Press home button
+ *
+ * To run only the presubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
+ *
+ * To run only the postsubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
+ *
+ * To run only the flaky assertions add: `--
+ *      --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
+ *
+ * Notes:
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [CloseAppTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
@@ -49,14 +74,23 @@
             }
         }
 
+    /** {@inheritDoc} */
     @FlakyTest
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
+    /** {@inheritDoc} */
     @Postsubmit
+    @Test
     override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
 
     companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+         * repetitions, screen orientation and navigation modes.
+         */
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun getParams(): Collection<FlickerTestParameter> {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index 3928476..511fc26 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -61,6 +61,10 @@
         }
     }
 
+    /**
+     * Entry point for the test runner. It will use this method to initialize and cache
+     * flicker executions
+     */
     @FlickerBuilderProvider
     fun buildFlicker(): FlickerBuilder {
         return FlickerBuilder(instrumentation).apply {
@@ -68,38 +72,60 @@
         }
     }
 
+    /**
+     * Checks that the navigation bar window is visible during the whole transition
+     */
     @Presubmit
     @Test
     open fun navBarWindowIsVisible() {
         testSpec.navBarWindowIsVisible()
     }
 
+    /**
+     * Checks that the status bar window is visible during the whole transition
+     */
     @Presubmit
     @Test
     open fun statusBarWindowIsVisible() {
         testSpec.statusBarWindowIsVisible()
     }
 
+    /**
+     * Checks that the navigation bar layer is visible during the whole transition
+     */
     @Presubmit
     @Test
     open fun navBarLayerIsVisible() {
         testSpec.navBarLayerIsVisible()
     }
 
+    /**
+     * Checks that the status bar layer is visible during the whole transition
+     */
     @Presubmit
     @Test
     open fun statusBarLayerIsVisible() {
         testSpec.statusBarLayerIsVisible()
     }
 
+    /**
+     * Checks the position of the navigation bar at the start and end of the transition
+     */
     @Presubmit
     @Test
     open fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales()
 
+    /**
+     * Checks the position of the status bar at the start and end of the transition
+     */
     @Presubmit
     @Test
     open fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
 
+    /**
+     * Checks that all windows that are visible on the trace, are visible for at least 2
+     * consecutive entries.
+     */
     @Presubmit
     @Test
     open fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
@@ -108,6 +134,10 @@
         }
     }
 
+    /**
+     * Checks that all layers that are visible on the trace, are visible for at least 2
+     * consecutive entries.
+     */
     @Presubmit
     @Test
     open fun visibleLayersShownMoreThanOneConsecutiveEntry() {
@@ -116,10 +146,17 @@
         }
     }
 
+    /**
+     * Checks that all parts of the screen are covered during the transition
+     */
     @Presubmit
     @Test
     open fun entireScreenCovered() = testSpec.entireScreenCovered()
 
+    /**
+     * Checks that [testApp] is the top visible app window at the start of the transition and
+     * that it is replaced by [LAUNCHER_COMPONENT] during the transition
+     */
     @Presubmit
     @Test
     open fun launcherReplacesAppWindowAsTopWindow() {
@@ -130,16 +167,23 @@
         }
     }
 
+    /**
+     * Checks that [LAUNCHER_COMPONENT] is invisible at the start of the transition and that
+     * it becomes visible during the transition
+     */
     @Presubmit
     @Test
     open fun launcherWindowBecomesVisible() {
         testSpec.assertWm {
-            this.isAppWindowInvisible(LAUNCHER_COMPONENT)
+            this.isAppWindowNotOnTop(LAUNCHER_COMPONENT)
                     .then()
                     .isAppWindowOnTop(LAUNCHER_COMPONENT)
         }
     }
 
+    /**
+     * Checks that [LAUNCHER_COMPONENT] layer becomes visible when [testApp] becomes invisible
+     */
     @Presubmit
     @Test
     open fun launcherLayerReplacesApp() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
index fad25b4..75900df 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+@file:JvmName("FlickerExtensions")
 package com.android.server.wm.flicker.helpers
 
 import com.android.server.wm.flicker.Flicker
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
index b22e241..0582685 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
@@ -110,7 +110,7 @@
         testSpec.assertWm {
             this.isAppWindowOnTop(testApp.component)
                 .then()
-                .appWindowNotOnTop(testApp.component)
+                .isAppWindowNotOnTop(testApp.component)
         }
     }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
new file mode 100644
index 0000000..bcb4417
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2021 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.flicker.ime
+
+import android.app.Instrumentation
+import android.platform.test.annotations.Postsubmit
+import android.view.Surface
+import android.view.WindowManagerPolicyConstants
+import androidx.test.filters.RequiresDevice
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.FlickerBuilderProvider
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.startRotation
+import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Launch an app that automatically displays the IME
+ *
+ * To run this test: `atest FlickerTests:LaunchAppShowImeOnStartTest`
+ *
+ * Actions:
+ *     Make sure no apps are running on the device
+ *     Launch an app [testApp] that automatically displays IME and wait animation to complete
+ *
+ * To run only the presubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
+ *
+ * To run only the postsubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
+ *
+ * To run only the flaky assertions add: `--
+ *      --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
+ *
+ * Notes:
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [CloseAppTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class LaunchAppShowImeOnStartTest(private val testSpec: FlickerTestParameter) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val testApp = ImeAppAutoFocusHelper(instrumentation, testSpec.config.startRotation)
+
+    @FlickerBuilderProvider
+    fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            setup {
+                eachRun {
+                    this.setRotation(testSpec.config.startRotation)
+                }
+            }
+            teardown {
+                eachRun {
+                    testApp.exit()
+                }
+            }
+            transitions {
+                testApp.launchViaIntent(wmHelper)
+                wmHelper.waitImeShown()
+            }
+        }
+    }
+
+    /**
+     * Checks that [FlickerComponentName.IME] window becomes visible during the transition
+     */
+    @Postsubmit
+    @Test
+    fun imeWindowBecomesVisible() = testSpec.imeWindowBecomesVisible()
+
+    /**
+     * Checks that [FlickerComponentName.IME] layer becomes visible during the transition
+     */
+    @Postsubmit
+    @Test
+    fun imeLayerBecomesVisible() = testSpec.imeLayerBecomesVisible()
+
+    /**
+     * Checks that [FlickerComponentName.IME] layer is invisible at the start of the transition
+     */
+    @Postsubmit
+    @Test
+    fun imeLayerNotExistsStart() {
+        testSpec.assertLayersStart {
+            this.isInvisible(FlickerComponentName.IME)
+        }
+    }
+
+    /**
+     * Checks that [FlickerComponentName.IME] layer is visible at the end of the transition
+     */
+    @Postsubmit
+    @Test
+    fun imeLayerExistsEnd() {
+        testSpec.assertLayersEnd {
+            this.isVisible(FlickerComponentName.IME)
+        }
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+         * repetitions, screen orientation and navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTestParameter> {
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigNonRotationTests(
+                    repetitions = 5,
+                    supportedRotations = listOf(Surface.ROTATION_0),
+                    supportedNavigationModes = listOf(
+                        WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
+                        WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+                    )
+                )
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
index ab641a7..7bf0186 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
@@ -20,6 +20,7 @@
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import android.view.WindowManagerPolicyConstants
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.server.wm.flicker.FlickerBuilderProvider
@@ -137,7 +138,7 @@
         }
     }
 
-    @Presubmit
+    @FlakyTest
     @Test
     fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
         testSpec.assertWm {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index f82ab22..f6febe9e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -136,9 +136,9 @@
         // Since we log 1x per frame, sometimes the activity visibility and the app visibility
         // are updated together, sometimes not, thus ignore activity check at the start
         testSpec.assertWm {
-            this.isAppWindowVisible(testApp.component, ignoreActivity = true)
+            this.isAppWindowVisible(testApp.component)
                     .then()
-                    .isAppWindowInvisible(testApp.component, ignoreActivity = true)
+                    .isAppWindowInvisible(testApp.component)
                     .then()
                     .isAppWindowVisible(testApp.component)
         }
@@ -153,7 +153,7 @@
         // and the app visibility are updated together, sometimes not, thus ignore activity
         // check at the start
         testSpec.assertWm {
-            this.isAppWindowVisible(testApp.component, ignoreActivity = true)
+            this.isAppWindowVisible(testApp.component)
         }
     }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
index 8cff595..4c506b0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
@@ -106,11 +106,12 @@
 
     @Test
     fun imeAppWindowVisibility() {
-        val component = FlickerComponentName(imeTestApp.`package`, "")
         testSpec.assertWm {
-            this.isAppWindowOnTop(component)
-                    .then()
-                    .isAppWindowVisible(component, ignoreActivity = true)
+            isAppWindowVisible(imeTestApp.component)
+                .then()
+                .isAppWindowVisible(testApp.component)
+                .then()
+                .isAppWindowVisible(imeTestApp.component)
         }
     }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
index d369de9..f74a771 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
@@ -40,7 +40,19 @@
 
 /**
  * Test the back and forward transition between 2 activities.
+ *
  * To run this test: `atest FlickerTests:ActivitiesTransitionTest`
+ *
+ * Actions:
+ *     Launch an app
+ *     Launch a secondary activity within the app
+ *     Close the secondary activity back to the initial one
+ *
+ * Notes:
+ *     1. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
@@ -51,6 +63,10 @@
     val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
     private val testApp: TwoActivitiesAppHelper = TwoActivitiesAppHelper(instrumentation)
 
+    /**
+     * Entry point for the test runner. It will use this method to initialize and cache
+     * flicker executions
+     */
     @FlickerBuilderProvider
     fun buildFlicker(): FlickerBuilder {
         return FlickerBuilder(instrumentation).apply {
@@ -76,6 +92,13 @@
         }
     }
 
+    /**
+     * Checks that the [ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME] activity is visible at
+     * the start of the transition, that
+     * [ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME] becomes visible during the
+     * transition, and that [ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME] is again visible
+     * at the end
+     */
     @Presubmit
     @Test
     fun finishSubActivity() {
@@ -92,18 +115,29 @@
         }
     }
 
+    /**
+     * Checks that all parts of the screen are covered during the transition
+     */
     @Presubmit
     @Test
     fun entireScreenCovered() = testSpec.entireScreenCovered()
 
+    /**
+     * Checks that the [LAUNCHER_COMPONENT] window is not on top. The launcher cannot be
+     * asserted with `isAppWindowVisible` because it contains 2 windows with the exact same name,
+     * and both are never simultaneously visible
+     */
     @Presubmit
     @Test
-    fun launcherWindowNotVisible() {
+    fun launcherWindowNotOnTop() {
         testSpec.assertWm {
-            this.isAppWindowInvisible(LAUNCHER_COMPONENT, ignoreActivity = true)
+            this.isAppWindowNotOnTop(LAUNCHER_COMPONENT)
         }
     }
 
+    /**
+     * Checks that the [LAUNCHER_COMPONENT] layer is never visible during the transition
+     */
     @Presubmit
     @Test
     fun launcherLayerNotVisible() {
@@ -111,6 +145,12 @@
     }
 
     companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+         * repetitions, screen orientation and navigation modes.
+         */
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun getParams(): Collection<FlickerTestParameter> {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index b842681..1bdc235 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -132,10 +132,9 @@
         testSpec.assertWm {
             this.notContains(testApp.component)
                     .then()
-                    .isAppWindowInvisible(testApp.component,
-                            ignoreActivity = true, isOptional = true)
+                    .isAppWindowInvisible(testApp.component, isOptional = true)
                     .then()
-                    .isAppWindowVisible(testApp.component, ignoreActivity = true)
+                    .isAppWindowVisible(testApp.component)
         }
     }
 
@@ -146,7 +145,7 @@
     @Test
     fun appWindowBecomesVisibleAtEnd() {
         testSpec.assertWmEnd {
-            this.isVisible(testApp.component)
+            this.isAppWindowVisible(testApp.component)
         }
     }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
index ee6e87d..7af7b3a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
@@ -40,6 +40,9 @@
 import com.android.server.wm.traces.common.FlickerComponentName
 import org.junit.Test
 
+/**
+ * Base class for app launch tests
+ */
 abstract class OpenAppTransition(protected val testSpec: FlickerTestParameter) {
     protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
     protected open val testApp: StandardAppHelper = SimpleAppHelper(instrumentation)
@@ -82,7 +85,7 @@
     }
 
     /**
-     * Checks that the navigation bar layer is visible during the whole transition
+     * Checks that the navigation bar layer is visible at the start and end of the trace
      */
     open fun navBarLayerIsVisible() {
         testSpec.navBarLayerIsVisible()
@@ -105,7 +108,7 @@
     }
 
     /**
-     * Checks that the status bar layer is visible during the whole transition
+     * Checks that the status bar layer is visible at the start and end of the trace
      */
     @Presubmit
     @Test
@@ -195,9 +198,9 @@
      */
     open fun launcherWindowBecomesInvisible() {
         testSpec.assertWm {
-            this.isAppWindowVisible(LAUNCHER_COMPONENT)
+            this.isAppWindowOnTop(LAUNCHER_COMPONENT)
                     .then()
-                    .isAppWindowInvisible(LAUNCHER_COMPONENT)
+                    .isAppWindowNotOnTop(LAUNCHER_COMPONENT)
         }
     }
 }
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index 6da01fa..52904cc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -191,7 +191,7 @@
                     .then()
                     .isAppWindowVisible(FlickerComponentName.SNAPSHOT, isOptional = true)
                     .then()
-                    .isAppWindowVisible(testApp1.component, ignoreActivity = true)
+                    .isAppWindowVisible(testApp1.component)
         }
     }
 
@@ -217,7 +217,7 @@
     @Test
     fun app2WindowBecomesAndStaysInvisible() {
         testSpec.assertWm {
-            this.isAppWindowVisible(testApp2.component, ignoreActivity = true)
+            this.isAppWindowVisible(testApp2.component)
                     .then()
                     .isAppWindowInvisible(testApp2.component)
         }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index a620e87..842aa2b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -209,7 +209,7 @@
                     .then()
                     .isAppWindowVisible(FlickerComponentName.SNAPSHOT, isOptional = true)
                     .then()
-                    .isAppWindowVisible(testApp2.component, ignoreActivity = true)
+                    .isAppWindowVisible(testApp2.component)
         }
     }
 
@@ -235,7 +235,7 @@
     @Test
     fun app1WindowBecomesAndStaysInvisible() {
         testSpec.assertWm {
-            this.isAppWindowVisible(testApp1.component, ignoreActivity = true)
+            this.isAppWindowVisible(testApp1.component)
                     .then()
                     .isAppWindowInvisible(testApp1.component)
         }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index 3feff04..10ca0d9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -145,7 +145,7 @@
     @Test
     fun startsWithHomeActivityFlaggedVisible() {
         testSpec.assertWmStart {
-            this.isHomeActivityVisible(true)
+            this.isHomeActivityVisible()
         }
     }
 
@@ -192,7 +192,7 @@
     @Test
     fun endsWithHomeActivityFlaggedInvisible() {
         testSpec.assertWmEnd {
-            this.isHomeActivityVisible(false)
+            this.isHomeActivityInvisible()
         }
     }
 
@@ -204,9 +204,9 @@
     @Test
     fun appWindowBecomesAndStaysVisible() {
         testSpec.assertWm {
-            this.isAppWindowInvisible(testApp.component, ignoreActivity = true)
+            this.isAppWindowInvisible(testApp.component)
                     .then()
-                    .isAppWindowVisible(testApp.component, ignoreActivity = true)
+                    .isAppWindowVisible(testApp.component)
         }
     }
 
@@ -232,9 +232,9 @@
     @Test
     fun launcherWindowBecomesAndStaysInvisible() {
         testSpec.assertWm {
-            this.isAppWindowVisible(LAUNCHER_COMPONENT)
+            this.isAppWindowOnTop(LAUNCHER_COMPONENT)
                     .then()
-                    .isAppWindowInvisible(LAUNCHER_COMPONENT)
+                    .isAppWindowNotOnTop(LAUNCHER_COMPONENT)
         }
     }
 
@@ -260,7 +260,7 @@
     @Test
     fun appWindowIsVisibleOnceLauncherWindowIsInvisible() {
         testSpec.assertWm {
-            this.isAppWindowVisible(LAUNCHER_COMPONENT)
+            this.isAppWindowOnTop(LAUNCHER_COMPONENT)
                     .then()
                     .isAppWindowVisible(FlickerComponentName.SNAPSHOT)
                     .then()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 624e0ec..4d4f266 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -36,8 +36,39 @@
 import org.junit.runners.Parameterized
 
 /**
- * Cycle through supported app rotations.
+ * Test opening an app and cycling through app rotations
+ *
+ * Currently runs:
+ *      0 -> 90 degrees
+ *      90 -> 0 degrees
+ *
+ * Actions:
+ *     Launch an app (via intent)
+ *     Set initial device orientation
+ *     Start tracing
+ *     Change device orientation
+ *     Stop tracing
+ *
  * To run this test: `atest FlickerTests:ChangeAppRotationTest`
+ *
+ * To run only the presubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
+ *
+ * To run only the postsubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
+ *
+ * To run only the flaky assertions add: `--
+ *      --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
+ *
+ * Notes:
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [RotationTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
@@ -58,15 +89,20 @@
             }
         }
 
+    /** {@inheritDoc} */
     @FlakyTest(bugId = 190185577)
     @Test
     override fun focusDoesNotChange() {
         super.focusDoesNotChange()
     }
 
+    /**
+     * Checks that the [FlickerComponentName.ROTATION] layer appears during the transition,
+     * doesn't flicker, and disappears before the transition is complete
+     */
     @Presubmit
     @Test
-    fun screenshotLayerBecomesInvisible() {
+    fun rotationLayerAppearsAndVanishes() {
         testSpec.assertLayers {
             this.isVisible(testApp.component)
                 .then()
@@ -76,34 +112,52 @@
         }
     }
 
+    /**
+     * Checks that the status bar window is visible and above the app windows in all WM
+     * trace entries
+     */
     @Presubmit
     @Test
     fun statusBarWindowIsVisible() {
         testSpec.statusBarWindowIsVisible()
     }
 
+    /**
+     * Checks that the status bar layer is visible at the start and end of the transition
+     */
     @Presubmit
     @Test
     fun statusBarLayerIsVisible() {
         testSpec.statusBarLayerIsVisible()
     }
 
+    /**
+     * Checks the position of the status bar at the start and end of the transition
+     */
     @Presubmit
     @Test
     fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
 
+    /** {@inheritDoc} */
     @FlakyTest
     @Test
     override fun navBarLayerRotatesAndScales() {
         super.navBarLayerRotatesAndScales()
     }
 
+    /** {@inheritDoc} */
     @FlakyTest
     @Test
     override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
         super.visibleLayersShownMoreThanOneConsecutiveEntry()
 
     companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestParameterFactory.getConfigRotationTests] for configuring
+         * repetitions, screen orientation and navigation modes.
+         */
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun getParams(): Collection<FlickerTestParameter> {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index 7f0ac12..e850632 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -33,6 +33,9 @@
 import com.android.server.wm.traces.common.FlickerComponentName
 import org.junit.Test
 
+/**
+ * Base class for app rotation tests
+ */
 abstract class RotationTransition(protected val testSpec: FlickerTestParameter) {
     protected abstract val testApp: StandardAppHelper
 
@@ -54,6 +57,10 @@
         }
     }
 
+    /**
+     * Entry point for the test runner. It will use this method to initialize and cache
+     * flicker executions
+     */
     @FlickerBuilderProvider
     fun buildFlicker(): FlickerBuilder {
         return FlickerBuilder(instrumentation).apply {
@@ -61,22 +68,36 @@
         }
     }
 
+    /**
+     * Checks that the navigation bar window is visible and above the app windows in all WM
+     * trace entries
+     */
     @Presubmit
     @Test
     open fun navBarWindowIsVisible() {
         testSpec.navBarWindowIsVisible()
     }
 
+    /**
+     * Checks that the navigation bar layer is visible at the start and end of the transition
+     */
     @Presubmit
     @Test
     open fun navBarLayerIsVisible() {
         testSpec.navBarLayerIsVisible()
     }
 
+    /**
+     * Checks the position of the navigation bar at the start and end of the transition
+     */
     @Presubmit
     @Test
     open fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales()
 
+    /**
+     * Checks that all layers that are visible on the trace, are visible for at least 2
+     * consecutive entries.
+     */
     @Presubmit
     @Test
     open fun visibleLayersShownMoreThanOneConsecutiveEntry() {
@@ -90,6 +111,10 @@
         }
     }
 
+    /**
+     * Checks that all windows that are visible on the trace, are visible for at least 2
+     * consecutive entries.
+     */
     @Presubmit
     @Test
     open fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
@@ -98,10 +123,16 @@
         }
     }
 
+    /**
+     * Checks that all parts of the screen are covered during the transition
+     */
     @Presubmit
     @Test
     open fun entireScreenCovered() = testSpec.entireScreenCovered()
 
+    /**
+     * Checks that the focus doesn't change during animation
+     */
     @Presubmit
     @Test
     open fun focusDoesNotChange() {
@@ -110,6 +141,9 @@
         }
     }
 
+    /**
+     * Checks that [testApp] layer covers the entire screen at the start of the transition
+     */
     @Presubmit
     @Test
     open fun appLayerRotates_StartingPos() {
@@ -120,6 +154,9 @@
         }
     }
 
+    /**
+     * Checks that [testApp] layer covers the entire screen at the end of the transition
+     */
     @Presubmit
     @Test
     open fun appLayerRotates_EndingPos() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index aed2ea6..310f04b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -35,8 +35,41 @@
 import org.junit.runners.Parameterized
 
 /**
- * Cycle through supported app rotations using seamless rotations.
+ * Test opening an app and cycling through app rotations using seamless rotations
+ *
+ * Currently runs:
+ *      0 -> 90 degrees
+ *      0 -> 90 degrees (with starved UI thread)
+ *      90 -> 0 degrees
+ *      90 -> 0 degrees (with starved UI thread)
+ *
+ * Actions:
+ *     Launch an app in fullscreen and supporting seamless rotation (via intent)
+ *     Set initial device orientation
+ *     Start tracing
+ *     Change device orientation
+ *     Stop tracing
+ *
  * To run this test: `atest FlickerTests:SeamlessAppRotationTest`
+ *
+ * To run only the presubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
+ *
+ * To run only the postsubmit assertions add: `--
+ *      --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
+ *      --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
+ *
+ * To run only the flaky assertions add: `--
+ *      --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
+ *
+ * Notes:
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited [RotationTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
@@ -61,6 +94,9 @@
             }
         }
 
+    /**
+     * Checks that [testApp] window is always in full screen
+     */
     @Presubmit
     @Test
     fun appWindowFullScreen() {
@@ -75,6 +111,9 @@
         }
     }
 
+    /**
+     * Checks that [testApp] window is always with seamless rotation
+     */
     @Presubmit
     @Test
     fun appWindowSeamlessRotation() {
@@ -90,6 +129,9 @@
         }
     }
 
+    /**
+     * Checks that [testApp] window is always visible
+     */
     @Presubmit
     @Test
     fun appLayerAlwaysVisible() {
@@ -98,6 +140,9 @@
         }
     }
 
+    /**
+     * Checks that [testApp] layer covers the entire screen during the whole transition
+     */
     @Presubmit
     @Test
     fun appLayerRotates() {
@@ -110,6 +155,10 @@
         }
     }
 
+    /**
+     * Checks that the [FlickerComponentName.STATUS_BAR] window is invisible during the whole
+     * transition
+     */
     @Presubmit
     @Test
     fun statusBarWindowIsAlwaysInvisible() {
@@ -118,6 +167,10 @@
         }
     }
 
+    /**
+     * Checks that the [FlickerComponentName.STATUS_BAR] layer is invisible during the whole
+     * transition
+     */
     @Presubmit
     @Test
     fun statusBarLayerIsAlwaysInvisible() {
@@ -126,13 +179,12 @@
         }
     }
 
+    /** {@inheritDoc} */
     @FlakyTest
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
     companion object {
-        private val testFactory = FlickerTestParameterFactory.getInstance()
-
         private val Map<String, Any?>.starveUiThread
             get() = this.getOrDefault(ActivityOptions.EXTRA_STARVE_UI_THREAD, false) as Boolean
 
@@ -144,20 +196,34 @@
             return config
         }
 
+        /**
+         * Creates the test configurations for seamless rotation based on the default rotation
+         * tests from [FlickerTestParameterFactory.getConfigRotationTests], but adding an
+         * additional flag ([ActivityOptions.EXTRA_STARVE_UI_THREAD]) to indicate if the app
+         * should starve the UI thread of not
+         */
         @JvmStatic
         private fun getConfigurations(): List<FlickerTestParameter> {
-            return testFactory.getConfigRotationTests(repetitions = 2).flatMap {
-                val defaultRun = it.createConfig(starveUiThread = false)
-                val busyUiRun = it.createConfig(starveUiThread = true)
-                listOf(
-                    FlickerTestParameter(defaultRun),
-                    FlickerTestParameter(busyUiRun,
-                        name = "${FlickerTestParameter.defaultName(busyUiRun)}_BUSY_UI_THREAD"
+            return FlickerTestParameterFactory.getInstance()
+                .getConfigRotationTests(repetitions = 2)
+                .flatMap {
+                    val defaultRun = it.createConfig(starveUiThread = false)
+                    val busyUiRun = it.createConfig(starveUiThread = true)
+                    listOf(
+                        FlickerTestParameter(defaultRun),
+                        FlickerTestParameter(busyUiRun,
+                            name = "${FlickerTestParameter.defaultName(busyUiRun)}_BUSY_UI_THREAD"
+                        )
                     )
-                )
-            }
+                }
         }
 
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestParameterFactory.getConfigRotationTests] for configuring
+         * repetitions, screen orientation and navigation modes.
+         */
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun getParams(): Collection<FlickerTestParameter> {