Merge "Support ignoring app orientation request per display"
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
index ecd1499..1be68f5 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
@@ -135,7 +135,6 @@
         final int mHeight;
         final Point mOutSurfaceSize = new Point();
         final SurfaceControl mOutSurfaceControl;
-        final SurfaceControl mOutBlastSurfaceControl = new SurfaceControl();
 
         final IntSupplier mViewVisibility;
 
@@ -158,7 +157,7 @@
                 session.relayout(mWindow, mParams, mWidth, mHeight,
                         mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrames,
                         mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls,
-                        mOutSurfaceSize, mOutBlastSurfaceControl);
+                        mOutSurfaceSize);
             }
         }
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 1a81587..81f22fe 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -2179,7 +2179,7 @@
                 if (getContext().getResources().getBoolean(
                         com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
                     mLocationRequest = new LocationRequest.Builder(/*intervalMillis=*/ 0)
-                        .setQuality(LocationRequest.ACCURACY_FINE)
+                        .setQuality(LocationRequest.QUALITY_HIGH_ACCURACY)
                         .setMaxUpdates(1)
                         .build();
                 }
diff --git a/api/current.txt b/api/current.txt
index e2adbc4..b1f6c06 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2889,6 +2889,7 @@
     field public static final int GESTURE_2_FINGER_DOUBLE_TAP = 20; // 0x14
     field public static final int GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD = 40; // 0x28
     field public static final int GESTURE_2_FINGER_SINGLE_TAP = 19; // 0x13
+    field public static final int GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD = 43; // 0x2b
     field public static final int GESTURE_2_FINGER_SWIPE_DOWN = 26; // 0x1a
     field public static final int GESTURE_2_FINGER_SWIPE_LEFT = 27; // 0x1b
     field public static final int GESTURE_2_FINGER_SWIPE_RIGHT = 28; // 0x1c
@@ -2897,11 +2898,13 @@
     field public static final int GESTURE_3_FINGER_DOUBLE_TAP = 23; // 0x17
     field public static final int GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD = 41; // 0x29
     field public static final int GESTURE_3_FINGER_SINGLE_TAP = 22; // 0x16
+    field public static final int GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD = 44; // 0x2c
     field public static final int GESTURE_3_FINGER_SWIPE_DOWN = 30; // 0x1e
     field public static final int GESTURE_3_FINGER_SWIPE_LEFT = 31; // 0x1f
     field public static final int GESTURE_3_FINGER_SWIPE_RIGHT = 32; // 0x20
     field public static final int GESTURE_3_FINGER_SWIPE_UP = 29; // 0x1d
     field public static final int GESTURE_3_FINGER_TRIPLE_TAP = 24; // 0x18
+    field public static final int GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD = 45; // 0x2d
     field public static final int GESTURE_4_FINGER_DOUBLE_TAP = 38; // 0x26
     field public static final int GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD = 42; // 0x2a
     field public static final int GESTURE_4_FINGER_SINGLE_TAP = 37; // 0x25
@@ -10664,12 +10667,15 @@
     field public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
     field public static final String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
+    field public static final String ACTION_PACKAGE_FULLY_LOADED = "android.intent.action.PACKAGE_FULLY_LOADED";
     field public static final String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field @Deprecated public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
     field public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
     field public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
     field public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
     field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
+    field public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
+    field public static final String ACTION_PACKAGE_UNSTARTABLE = "android.intent.action.PACKAGE_UNSTARTABLE";
     field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
     field public static final String ACTION_PASTE = "android.intent.action.PASTE";
     field public static final String ACTION_PICK = "android.intent.action.PICK";
@@ -10834,6 +10840,7 @@
     field public static final String EXTRA_TIMEZONE = "time-zone";
     field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
     field public static final String EXTRA_UID = "android.intent.extra.UID";
+    field public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
     field public static final String EXTRA_USER = "android.intent.extra.USER";
     field public static final int FILL_IN_ACTION = 1; // 0x1
     field public static final int FILL_IN_CATEGORIES = 4; // 0x4
@@ -12293,6 +12300,9 @@
     field public static final int SYNCHRONOUS = 2; // 0x2
     field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL;
     field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE;
+    field public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1; // 0x1
+    field public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2; // 0x2
+    field public static final int UNSTARTABLE_REASON_UNKNOWN = 0; // 0x0
     field public static final int VERIFICATION_ALLOW = 1; // 0x1
     field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
     field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
@@ -24089,9 +24099,13 @@
     method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
     method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
     method @IntRange(from=0) public long getMinUpdateIntervalMillis();
+    method public int getQuality();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
     field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
+    field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
+    field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
+    field public static final int QUALITY_LOW_POWER = 104; // 0x68
   }
 
   public static final class LocationRequest.Builder {
@@ -24104,6 +24118,7 @@
     method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
     method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
     method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
+    method @NonNull public android.location.LocationRequest.Builder setQuality(int);
   }
 
   public interface OnNmeaMessageListener {
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index dc92b52..e825b62 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -1,10 +1,20 @@
 // Signature format: 2.0
 package android.app {
 
+  public class ActivityManager {
+    method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
+    method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
+  }
+
   public class AppOpsManager {
     field public static final String OPSTR_NO_ISOLATED_STORAGE = "android:no_isolated_storage";
   }
 
+  public abstract class HomeVisibilityListener {
+    ctor public HomeVisibilityListener();
+    method public abstract void onHomeVisibilityChanged(boolean);
+  }
+
   public class NotificationManager {
     method public boolean hasEnabledNotificationListener(@NonNull String, @NonNull android.os.UserHandle);
     field public static final String ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED = "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED";
@@ -178,6 +188,18 @@
 
 }
 
+package android.telephony {
+
+  public abstract class CellSignalStrength {
+    method public static int getNumSignalStrengthLevels();
+  }
+
+  public class TelephonyManager {
+    method @NonNull public static int[] getAllNetworkTypes();
+  }
+
+}
+
 package android.util {
 
   public class AtomicFile {
diff --git a/api/system-current.txt b/api/system-current.txt
index 2e53058..b6b6e5b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -122,6 +122,7 @@
     field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
     field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
     field public static final String MANAGE_MUSIC_RECOGNITION = "android.permission.MANAGE_MUSIC_RECOGNITION";
+    field public static final String MANAGE_NOTIFICATION_LISTENERS = "android.permission.MANAGE_NOTIFICATION_LISTENERS";
     field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS";
     field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
     field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
@@ -674,8 +675,10 @@
   public class NotificationManager {
     method @NonNull public java.util.List<java.lang.String> getAllowedAssistantAdjustments();
     method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
+    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners();
     method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
     method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean);
     field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL = "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL";
     field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL = "android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL";
     field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL = "android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL";
@@ -4171,7 +4174,6 @@
     method @Deprecated public long getInterval();
     method @Deprecated public int getNumUpdates();
     method @Deprecated @NonNull public String getProvider();
-    method public int getQuality();
     method @Deprecated public float getSmallestDisplacement();
     method @NonNull public android.os.WorkSource getWorkSource();
     method public boolean isHiddenFromAppOps();
@@ -4190,11 +4192,11 @@
     method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
     method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
     method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
-    field public static final int ACCURACY_BLOCK = 102; // 0x66
-    field public static final int ACCURACY_CITY = 104; // 0x68
-    field public static final int ACCURACY_FINE = 100; // 0x64
-    field public static final int POWER_HIGH = 203; // 0xcb
-    field public static final int POWER_LOW = 201; // 0xc9
+    field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
+    field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
+    field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
+    field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
+    field @Deprecated public static final int POWER_LOW = 201; // 0xc9
     field @Deprecated public static final int POWER_NONE = 200; // 0xc8
   }
 
@@ -4202,7 +4204,6 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
     method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
     method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
-    method @NonNull public android.location.LocationRequest.Builder setQuality(int);
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
   }
 
@@ -4769,6 +4770,22 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.DvbDeviceInfo> CREATOR;
   }
 
+  public final class TunedInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getAppTag();
+    method public int getAppType();
+    method @Nullable public android.net.Uri getChannelUri();
+    method @NonNull public String getInputId();
+    method public boolean isForeground();
+    method public boolean isRecordingSession();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int APP_TAG_SELF = 0; // 0x0
+    field public static final int APP_TYPE_NON_SYSTEM = 3; // 0x3
+    field public static final int APP_TYPE_SELF = 1; // 0x1
+    field public static final int APP_TYPE_SYSTEM = 2; // 0x2
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.TunedInfo> CREATOR;
+  }
+
   public final class TvContentRatingSystemInfo implements android.os.Parcelable {
     method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo);
     method public int describeContents();
@@ -4884,6 +4901,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating);
     method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig);
     method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String);
+    method @NonNull @RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS") public java.util.List<android.media.tv.TunedInfo> getCurrentTunedInfos();
     method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList();
     method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList();
     method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList();
@@ -4909,6 +4927,10 @@
     method public abstract void onStreamConfigChanged(android.media.tv.TvStreamConfig[]);
   }
 
+  public abstract static class TvInputManager.TvInputCallback {
+    method public void onCurrentTunedInfosUpdated(@NonNull java.util.List<android.media.tv.TunedInfo>);
+  }
+
   public abstract class TvInputService extends android.app.Service {
     method @Nullable public android.media.tv.TvInputInfo onHardwareAdded(android.media.tv.TvInputHardwareInfo);
     method @Nullable public String onHardwareRemoved(android.media.tv.TvInputHardwareInfo);
@@ -5036,6 +5058,7 @@
     method @Nullable public android.media.tv.tuner.DemuxCapabilities getDemuxCapabilities();
     method @Nullable public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
     method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
+    method public int linkFrontendToCiCam(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler();
     method @Nullable public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
     method @Nullable public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnRecordStatusChangedListener);
@@ -5049,10 +5072,13 @@
     method public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener);
     method public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner);
     method public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings);
+    method public int unlinkFrontendToCiCam(int);
     method public void updateResourcePriority(int, int);
     field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff
     field public static final int INVALID_FILTER_ID = -1; // 0xffffffff
     field public static final long INVALID_FILTER_ID_64BIT = -1L; // 0xffffffffffffffffL
+    field public static final int INVALID_FRONTEND_SETTING_FREQUENCY = -1; // 0xffffffff
+    field public static final int INVALID_LTS_ID = -1; // 0xffffffff
     field public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1; // 0xffffffff
     field public static final int INVALID_STREAM_ID = 65535; // 0xffff
     field public static final long INVALID_TIMESTAMP = -1L; // 0xffffffffffffffffL
@@ -5265,16 +5291,19 @@
     method @NonNull public static android.media.tv.tuner.filter.IpFilterConfiguration.Builder builder();
     method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress();
     method public int getDstPort();
+    method public int getIpFilterContextId();
     method @NonNull @Size(min=4, max=16) public byte[] getSrcIpAddress();
     method public int getSrcPort();
     method public int getType();
     method public boolean isPassthrough();
+    field public static final int INVALID_IP_FILTER_CONTEXT_ID = -1; // 0xffffffff
   }
 
   public static final class IpFilterConfiguration.Builder {
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration build();
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstIpAddress(@NonNull byte[]);
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstPort(int);
+    method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setIpFilterContextId(int);
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setPassthrough(boolean);
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSettings(@Nullable android.media.tv.tuner.filter.Settings);
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSrcIpAddress(@NonNull byte[]);
@@ -5494,9 +5523,13 @@
 
   public class AnalogFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
     method @NonNull public static android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder builder();
+    method public int getAftFlag();
     method public int getSifStandard();
     method public int getSignalType();
     method public int getType();
+    field public static final int AFT_FLAG_FALSE = 2; // 0x2
+    field public static final int AFT_FLAG_TRUE = 1; // 0x1
+    field public static final int AFT_FLAG_UNDEFINED = 0; // 0x0
     field public static final int SIF_AUTO = 1; // 0x1
     field public static final int SIF_BG = 2; // 0x2
     field public static final int SIF_BG_A2 = 4; // 0x4
@@ -5529,6 +5562,7 @@
 
   public static class AnalogFrontendSettings.Builder {
     method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setAftFlag(int);
     method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setFrequency(int);
     method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSifStandard(int);
     method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSignalType(int);
@@ -5658,6 +5692,7 @@
     method public int getOuterFec();
     method public int getSpectralInversion();
     method public int getSymbolRate();
+    method public int getTimeInterleaveMode();
     method public int getType();
     field public static final int ANNEX_A = 1; // 0x1
     field public static final int ANNEX_B = 2; // 0x2
@@ -5676,6 +5711,17 @@
     field public static final int SPECTRAL_INVERSION_INVERTED = 2; // 0x2
     field public static final int SPECTRAL_INVERSION_NORMAL = 1; // 0x1
     field public static final int SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0
+    field public static final int TIME_INTERLEAVE_MODE_128_1_0 = 2; // 0x2
+    field public static final int TIME_INTERLEAVE_MODE_128_1_1 = 4; // 0x4
+    field public static final int TIME_INTERLEAVE_MODE_128_2 = 128; // 0x80
+    field public static final int TIME_INTERLEAVE_MODE_128_3 = 256; // 0x100
+    field public static final int TIME_INTERLEAVE_MODE_128_4 = 512; // 0x200
+    field public static final int TIME_INTERLEAVE_MODE_16_8 = 32; // 0x20
+    field public static final int TIME_INTERLEAVE_MODE_32_4 = 16; // 0x10
+    field public static final int TIME_INTERLEAVE_MODE_64_2 = 8; // 0x8
+    field public static final int TIME_INTERLEAVE_MODE_8_16 = 64; // 0x40
+    field public static final int TIME_INTERLEAVE_MODE_AUTO = 1; // 0x1
+    field public static final int TIME_INTERLEAVE_MODE_UNDEFINED = 0; // 0x0
   }
 
   public static class DvbcFrontendSettings.Builder {
@@ -5687,6 +5733,7 @@
     method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setOuterFec(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSpectralInversion(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSymbolRate(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setTimeInterleaveMode(int);
   }
 
   public class DvbsCodeRate {
@@ -5718,6 +5765,7 @@
     method public int getModulation();
     method public int getPilot();
     method public int getRolloff();
+    method public int getScanType();
     method public int getStandard();
     method public int getSymbolRate();
     method public int getType();
@@ -5748,6 +5796,11 @@
     field public static final int ROLLOFF_0_35 = 1; // 0x1
     field public static final int ROLLOFF_0_5 = 6; // 0x6
     field public static final int ROLLOFF_UNDEFINED = 0; // 0x0
+    field public static final int SCAN_TYPE_DIRECT = 1; // 0x1
+    field public static final int SCAN_TYPE_DISEQC = 2; // 0x2
+    field public static final int SCAN_TYPE_JESS = 4; // 0x4
+    field public static final int SCAN_TYPE_UNDEFINED = 0; // 0x0
+    field public static final int SCAN_TYPE_UNICABLE = 3; // 0x3
     field public static final int STANDARD_AUTO = 1; // 0x1
     field public static final int STANDARD_S = 2; // 0x2
     field public static final int STANDARD_S2 = 4; // 0x4
@@ -5765,6 +5818,7 @@
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setPilot(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setRolloff(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setScanType(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setStandard(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setSymbolRate(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setVcmMode(int);
@@ -5817,10 +5871,14 @@
     field public static final int CODERATE_AUTO = 1; // 0x1
     field public static final int CODERATE_UNDEFINED = 0; // 0x0
     field public static final int CONSTELLATION_16QAM = 4; // 0x4
+    field public static final int CONSTELLATION_16QAM_R = 64; // 0x40
     field public static final int CONSTELLATION_256QAM = 16; // 0x10
+    field public static final int CONSTELLATION_256QAM_R = 256; // 0x100
     field public static final int CONSTELLATION_64QAM = 8; // 0x8
+    field public static final int CONSTELLATION_64QAM_R = 128; // 0x80
     field public static final int CONSTELLATION_AUTO = 1; // 0x1
     field public static final int CONSTELLATION_QPSK = 2; // 0x2
+    field public static final int CONSTELLATION_QPSK_R = 32; // 0x20
     field public static final int CONSTELLATION_UNDEFINED = 0; // 0x0
     field public static final int GUARD_INTERVAL_19_128 = 64; // 0x40
     field public static final int GUARD_INTERVAL_19_256 = 128; // 0x80
@@ -5854,6 +5912,9 @@
     field public static final int TRANSMISSION_MODE_4K = 8; // 0x8
     field public static final int TRANSMISSION_MODE_8K = 4; // 0x4
     field public static final int TRANSMISSION_MODE_AUTO = 1; // 0x1
+    field public static final int TRANSMISSION_MODE_EXTENDED_16K = 256; // 0x100
+    field public static final int TRANSMISSION_MODE_EXTENDED_32K = 512; // 0x200
+    field public static final int TRANSMISSION_MODE_EXTENDED_8K = 128; // 0x80
     field public static final int TRANSMISSION_MODE_UNDEFINED = 0; // 0x0
   }
 
@@ -5891,8 +5952,12 @@
   }
 
   public abstract class FrontendSettings {
+    method public int getEndFrequency();
     method public int getFrequency();
+    method public int getFrontendSpectralInversion();
     method public abstract int getType();
+    method @IntRange(from=1) public void setEndFrequency(int);
+    method public void setSpectralInversion(int);
     field public static final long FEC_11_15 = 4194304L; // 0x400000L
     field public static final long FEC_11_20 = 8388608L; // 0x800000L
     field public static final long FEC_11_45 = 16777216L; // 0x1000000L
@@ -5930,6 +5995,9 @@
     field public static final long FEC_9_20 = 2097152L; // 0x200000L
     field public static final long FEC_AUTO = 1L; // 0x1L
     field public static final long FEC_UNDEFINED = 0L; // 0x0L
+    field public static final int FRONTEND_SPECTRAL_INVERSION_INVERTED = 2; // 0x2
+    field public static final int FRONTEND_SPECTRAL_INVERSION_NORMAL = 1; // 0x1
+    field public static final int FRONTEND_SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0
     field public static final int TYPE_ANALOG = 1; // 0x1
     field public static final int TYPE_ATSC = 2; // 0x2
     field public static final int TYPE_ATSC3 = 3; // 0x3
@@ -11040,6 +11108,25 @@
     field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
   }
 
+  public final class ModemActivityInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo);
+    method public long getIdleTimeMillis();
+    method public static int getNumTxPowerLevels();
+    method public long getReceiveTimeMillis();
+    method public long getSleepTimeMillis();
+    method public long getTimestampMillis();
+    method public long getTransmitDurationMillisAtPowerLevel(int);
+    method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
+    field public static final int TX_POWER_LEVEL_0 = 0; // 0x0
+    field public static final int TX_POWER_LEVEL_1 = 1; // 0x1
+    field public static final int TX_POWER_LEVEL_2 = 2; // 0x2
+    field public static final int TX_POWER_LEVEL_3 = 3; // 0x3
+    field public static final int TX_POWER_LEVEL_4 = 4; // 0x4
+  }
+
   public final class NetworkRegistrationInfo implements android.os.Parcelable {
     method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
     method public int getRegistrationState();
diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt
index 7195144..773ecd03 100644
--- a/api/system-lint-baseline.txt
+++ b/api/system-lint-baseline.txt
@@ -159,8 +159,6 @@
     
 MissingNullability: android.telephony.ModemActivityInfo#writeToParcel(android.os.Parcel, int) parameter #0:
     
-MissingNullability: android.telephony.ModemActivityInfo.TransmitPower#toString():
-    
 MissingNullability: android.telephony.NetworkService#onUnbind(android.content.Intent) parameter #0:
     
 MissingNullability: android.telephony.SmsCbCmasInfo#toString():
diff --git a/api/test-current.txt b/api/test-current.txt
index e7c6445..b34c948 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -14,6 +14,7 @@
     field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
     field public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
     field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES";
+    field public static final String MANAGE_NOTIFICATION_LISTENERS = "android.permission.MANAGE_NOTIFICATION_LISTENERS";
     field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
     field public static final String NETWORK_SETTINGS = "android.permission.NETWORK_SETTINGS";
     field public static final String NETWORK_STACK = "android.permission.NETWORK_STACK";
@@ -79,6 +80,7 @@
   }
 
   public class ActivityManager {
+    method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
     method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
     method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void forceStopPackage(String);
@@ -88,6 +90,7 @@
     method @RequiresPermission(android.Manifest.permission.INJECT_EVENTS) public void holdLock(int);
     method public static boolean isHighEndGfx();
     method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void killProcessesWhenImperceptible(@NonNull int[], @NonNull String);
+    method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
     method @RequiresPermission(android.Manifest.permission.RESET_APP_ERRORS) public void resetAppErrors();
     method public static void resumeAppSwitches() throws android.os.RemoteException;
@@ -458,6 +461,11 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void stopDream();
   }
 
+  public abstract class HomeVisibilityListener {
+    ctor public HomeVisibilityListener();
+    method public abstract void onHomeVisibilityChanged(boolean);
+  }
+
   public final class NotificationChannel implements android.os.Parcelable {
     method public int getOriginalImportance();
     method public boolean isBlockable();
@@ -487,9 +495,11 @@
     method @NonNull public java.util.List<java.lang.String> getAllowedAssistantAdjustments();
     method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
     method public android.content.ComponentName getEffectsSuppressor();
+    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners();
     method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
     method public boolean matchesCallFilter(android.os.Bundle);
     method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean);
     method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel);
   }
 
@@ -1227,20 +1237,19 @@
 package android.hardware.biometrics {
 
   public class BiometricManager {
-    method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession getTestSession();
+    method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession createTestSession(int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties();
   }
 
   public class BiometricTestSession implements java.lang.AutoCloseable {
-    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void authenticateReject(int, int);
-    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void authenticateSuccess(int, int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void acceptAuthentication(int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void cleanupInternalState(int);
     method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void close();
-    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enableTestHal(int, boolean);
-    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enrollFinish(int, int);
-    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enrollStart(int, int);
-    method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties();
-    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void internalCleanup(int, int);
-    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyAcquired(int, int);
-    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyError(int, int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void finishEnroll(int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyAcquired(int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyError(int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void rejectAuthentication(int);
+    method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void startEnroll(int);
   }
 
   public class SensorProperties {
@@ -1361,7 +1370,8 @@
 package android.hardware.fingerprint {
 
   @Deprecated public class FingerprintManager {
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession getTestSession();
+    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession createTestSession(int);
+    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties();
   }
 
 }
@@ -1767,11 +1777,11 @@
     method public boolean isHiddenFromAppOps();
     method public boolean isLocationSettingsIgnored();
     method public boolean isLowPower();
-    field public static final int ACCURACY_BLOCK = 102; // 0x66
-    field public static final int ACCURACY_CITY = 104; // 0x68
-    field public static final int ACCURACY_FINE = 100; // 0x64
-    field public static final int POWER_HIGH = 203; // 0xcb
-    field public static final int POWER_LOW = 201; // 0xc9
+    field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
+    field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
+    field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
+    field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
+    field @Deprecated public static final int POWER_LOW = 201; // 0xc9
   }
 
   public static final class LocationRequest.Builder {
@@ -4233,6 +4243,27 @@
     field public static final String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override";
   }
 
+  public final class ModemActivityInfo implements android.os.Parcelable {
+    ctor public ModemActivityInfo(long, int, int, @NonNull int[], int);
+    method public int describeContents();
+    method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo);
+    method public long getIdleTimeMillis();
+    method public static int getNumTxPowerLevels();
+    method public long getReceiveTimeMillis();
+    method public long getSleepTimeMillis();
+    method public long getTimestampMillis();
+    method public long getTransmitDurationMillisAtPowerLevel(int);
+    method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int);
+    method public boolean isValid();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
+    field public static final int TX_POWER_LEVEL_0 = 0; // 0x0
+    field public static final int TX_POWER_LEVEL_1 = 1; // 0x1
+    field public static final int TX_POWER_LEVEL_2 = 2; // 0x2
+    field public static final int TX_POWER_LEVEL_3 = 3; // 0x3
+    field public static final int TX_POWER_LEVEL_4 = 4; // 0x4
+  }
+
   public final class NetworkRegistrationInfo implements android.os.Parcelable {
     method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
     method public int getRegistrationState();
@@ -5785,6 +5816,15 @@
     field public static final int FEATURE_WINDOW_TOKENS = 2; // 0x2
   }
 
+  public final class TaskAppearedInfo implements android.os.Parcelable {
+    ctor public TaskAppearedInfo(@NonNull android.app.ActivityManager.RunningTaskInfo, @NonNull android.view.SurfaceControl);
+    method public int describeContents();
+    method @NonNull public android.view.SurfaceControl getLeash();
+    method @NonNull public android.app.ActivityManager.RunningTaskInfo getTaskInfo();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.window.TaskAppearedInfo> CREATOR;
+  }
+
   public class TaskOrganizer extends android.window.WindowOrganizer {
     ctor public TaskOrganizer();
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.app.ActivityManager.RunningTaskInfo createRootTask(int, int);
@@ -5796,10 +5836,10 @@
     method @BinderThread public void onTaskAppeared(@NonNull android.app.ActivityManager.RunningTaskInfo, @NonNull android.view.SurfaceControl);
     method @BinderThread public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo);
     method @BinderThread public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void registerOrganizer();
+    method @CallSuper @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public java.util.List<android.window.TaskAppearedInfo> registerOrganizer();
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(@NonNull android.window.WindowContainerToken, boolean);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setLaunchRoot(int, @NonNull android.window.WindowContainerToken);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void unregisterOrganizer();
+    method @CallSuper @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void unregisterOrganizer();
   }
 
   public final class WindowContainerToken implements android.os.Parcelable {
diff --git a/core/java/android/accessibilityservice/AccessibilityGestureEvent.java b/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
index 25729ab..e3139eb 100644
--- a/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
+++ b/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
@@ -20,6 +20,7 @@
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_DOUBLE_TAP;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SINGLE_TAP;
+import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_DOWN;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_LEFT;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_RIGHT;
@@ -28,11 +29,13 @@
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_DOUBLE_TAP;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SINGLE_TAP;
+import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_DOWN;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_LEFT;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_RIGHT;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_UP;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_TRIPLE_TAP;
+import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_DOUBLE_TAP;
 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_SINGLE_TAP;
@@ -85,13 +88,16 @@
     /** @hide */
     @IntDef(prefix = { "GESTURE_" }, value = {
             GESTURE_2_FINGER_SINGLE_TAP,
+            GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD,
             GESTURE_2_FINGER_DOUBLE_TAP,
             GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD,
             GESTURE_2_FINGER_TRIPLE_TAP,
             GESTURE_3_FINGER_SINGLE_TAP,
+            GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD,
             GESTURE_3_FINGER_DOUBLE_TAP,
             GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD,
             GESTURE_3_FINGER_TRIPLE_TAP,
+            GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD,
             GESTURE_DOUBLE_TAP,
             GESTURE_DOUBLE_TAP_AND_HOLD,
             GESTURE_SWIPE_UP,
@@ -180,15 +186,21 @@
     private static String eventTypeToString(int eventType) {
         switch (eventType) {
             case GESTURE_2_FINGER_SINGLE_TAP: return "GESTURE_2_FINGER_SINGLE_TAP";
+            case GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD:
+                return "GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD";
             case GESTURE_2_FINGER_DOUBLE_TAP: return "GESTURE_2_FINGER_DOUBLE_TAP";
             case GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD:
                 return "GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD";
             case GESTURE_2_FINGER_TRIPLE_TAP: return "GESTURE_2_FINGER_TRIPLE_TAP";
             case GESTURE_3_FINGER_SINGLE_TAP: return "GESTURE_3_FINGER_SINGLE_TAP";
+            case GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD:
+                return "GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD";
             case GESTURE_3_FINGER_DOUBLE_TAP: return "GESTURE_3_FINGER_DOUBLE_TAP";
             case GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD:
                 return "GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD";
             case GESTURE_3_FINGER_TRIPLE_TAP: return "GESTURE_3_FINGER_TRIPLE_TAP";
+            case GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD:
+                return "GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD";
             case GESTURE_4_FINGER_SINGLE_TAP: return "GESTURE_4_FINGER_SINGLE_TAP";
             case GESTURE_4_FINGER_DOUBLE_TAP: return "GESTURE_4_FINGER_DOUBLE_TAP";
             case GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD:
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index b5b0ce3..7c6d448 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -421,6 +421,15 @@
     /** The user has performed a three-finger double tap and hold gesture on the touch screen. */
     public static final int GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD = 41;
 
+    /** The user has performed a two-finger  single-tap and hold gesture on the touch screen. */
+    public static final int GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD = 43;
+
+    /** The user has performed a three-finger  single-tap and hold gesture on the touch screen. */
+    public static final int GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD = 44;
+
+    /** The user has performed a three-finger  triple-tap and hold gesture on the touch screen. */
+    public static final int GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD = 45;
+
     /** The user has performed a two-finger double tap and hold gesture on the touch screen. */
     public static final int GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD = 42;
 
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index e75d2f6..30efb48 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -100,6 +100,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.Executor;
 
 /**
  * <p>
@@ -4752,31 +4753,43 @@
     }
 
     /**
-     * Register with {@link HomeVisibilityObserver} with ActivityManager.
-     * TODO: b/144351078 expose as SystemApi
+     * Register to be notified when the visibility of the home screen changes.
+     *
+     * @param executor The executor on which the listener should be called.
+     * @param listener The listener that is called when home visibility changes.
      * @hide
      */
-    public void registerHomeVisibilityObserver(@NonNull HomeVisibilityObserver observer) {
-        Preconditions.checkNotNull(observer);
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
+    public void addHomeVisibilityListener(@NonNull Executor executor,
+            @NonNull HomeVisibilityListener listener) {
+        Preconditions.checkNotNull(listener);
+        Preconditions.checkNotNull(executor);
         try {
-            observer.init(mContext, this);
-            getService().registerProcessObserver(observer.mObserver);
+            listener.init(mContext, executor, this);
+            getService().registerProcessObserver(listener.mObserver);
             // Notify upon first registration.
-            observer.onHomeVisibilityChanged(observer.mIsHomeActivityVisible);
+            executor.execute(() ->
+                    listener.onHomeVisibilityChanged(listener.mIsHomeActivityVisible));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Unregister with {@link HomeVisibilityObserver} with ActivityManager.
-     * TODO: b/144351078 expose as SystemApi
+     * Removes a listener that was previously added with {@link #addHomeVisibilityListener}.
+     *
+     * @param listener The listener that was previously added.
      * @hide
      */
-    public void unregisterHomeVisibilityObserver(@NonNull HomeVisibilityObserver observer) {
-        Preconditions.checkNotNull(observer);
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
+    public void removeHomeVisibilityListener(@NonNull HomeVisibilityListener listener) {
+        Preconditions.checkNotNull(listener);
         try {
-            getService().unregisterProcessObserver(observer.mObserver);
+            getService().unregisterProcessObserver(listener.mObserver);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/HomeVisibilityListener.java b/core/java/android/app/HomeVisibilityListener.java
new file mode 100644
index 0000000..c6e5699
--- /dev/null
+++ b/core/java/android/app/HomeVisibilityListener.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 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 android.app;
+
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.content.Context;
+import android.os.Binder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * A listener that will be invoked when the visibility of the home screen changes.
+ * Register this callback via {@link ActivityManager#addHomeVisibilityListener}
+ * @hide
+ */
+// This is a single-method listener that needs a bunch of supporting code, so it can't be an
+// interface
+@SuppressLint("ListenerInterface")
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+@TestApi
+public abstract class HomeVisibilityListener {
+    private Context mContext;
+    private ActivityManager mActivityManager;
+    private Executor mExecutor;
+    /** @hide */
+    android.app.IProcessObserver.Stub mObserver;
+    /** @hide */
+    boolean mIsHomeActivityVisible;
+
+    /** @hide */
+    void init(Context context, Executor executor, ActivityManager activityManager) {
+        mContext = context;
+        mActivityManager = activityManager;
+        mIsHomeActivityVisible = isHomeActivityVisible();
+        mExecutor = executor;
+    }
+
+    /**
+     * Called when the visibility of the home screen changes.
+     *
+     * @param isHomeActivityVisible Whether the home screen activity is now visible.
+     */
+    public abstract void onHomeVisibilityChanged(boolean isHomeActivityVisible);
+
+    public HomeVisibilityListener() {
+        mObserver = new android.app.IProcessObserver.Stub() {
+            @Override
+            public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) {
+                refreshHomeVisibility();
+            }
+
+            @Override
+            public void onForegroundServicesChanged(int pid, int uid, int fgServiceTypes) {
+            }
+
+            @Override
+            public void onProcessDied(int pid, int uid) {
+                refreshHomeVisibility();
+            }
+
+            private void refreshHomeVisibility() {
+                boolean isHomeActivityVisible = isHomeActivityVisible();
+                if (mIsHomeActivityVisible != isHomeActivityVisible) {
+                    mIsHomeActivityVisible = isHomeActivityVisible;
+                    Binder.withCleanCallingIdentity(() ->
+                            mExecutor.execute(() ->
+                                    onHomeVisibilityChanged(mIsHomeActivityVisible)));
+                }
+            }
+        };
+    }
+
+    private boolean isHomeActivityVisible() {
+        List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
+        if (tasks == null || tasks.isEmpty()) {
+            return false;
+        }
+
+        String top = tasks.get(0).topActivity.getPackageName();
+        if (top == null) {
+            return false;
+        }
+
+        // We can assume that the screen is idle if the home application is in the foreground.
+        String defaultHomePackage = mContext.getPackageManager()
+                .getHomeActivities(new ArrayList<>()).getPackageName();
+        if (Objects.equals(top, defaultHomePackage)) {
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/core/java/android/app/HomeVisibilityObserver.java b/core/java/android/app/HomeVisibilityObserver.java
deleted file mode 100644
index 8422c6f..0000000
--- a/core/java/android/app/HomeVisibilityObserver.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2020 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 android.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-
-import java.util.List;
-
-/**
- * An observer / callback to create and register by
- * {@link ActivityManager#registerHomeVisibilityObserver} so that it's triggered when
- * visibility of home page changes.
- * TODO: b/144351078 expose as SystemApi
- * @hide
- */
-public abstract class HomeVisibilityObserver {
-    private Context mContext;
-    private ActivityManager mActivityManager;
-    /** @hide */
-    IProcessObserver.Stub mObserver;
-    /** @hide */
-    boolean mIsHomeActivityVisible;
-
-    /** @hide */
-    void init(Context context, ActivityManager activityManager) {
-        mContext = context;
-        mActivityManager = activityManager;
-        mIsHomeActivityVisible = isHomeActivityVisible();
-    }
-
-    /**
-     * The API that needs implemented and will be triggered when activity on home page changes.
-     */
-    public abstract void onHomeVisibilityChanged(boolean isHomeActivityVisible);
-
-    public HomeVisibilityObserver() {
-        mObserver = new IProcessObserver.Stub() {
-            @Override
-            public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) {
-                boolean isHomeActivityVisible = isHomeActivityVisible();
-                if (mIsHomeActivityVisible != isHomeActivityVisible) {
-                    mIsHomeActivityVisible = isHomeActivityVisible;
-                    onHomeVisibilityChanged(mIsHomeActivityVisible);
-                }
-            }
-
-            @Override
-            public void onForegroundServicesChanged(int pid, int uid, int fgServiceTypes) {
-            }
-
-            @Override
-            public void onProcessDied(int pid, int uid) {
-            }
-        };
-    }
-
-    private boolean isHomeActivityVisible() {
-        List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
-        if (tasks == null || tasks.isEmpty()) {
-            return false;
-        }
-
-        String top = tasks.get(0).topActivity.getPackageName();
-        if (top == null) {
-            return false;
-        }
-
-        // We can assume that the screen is idle if the home application is in the foreground.
-        final Intent intent = new Intent(Intent.ACTION_MAIN, null);
-        intent.addCategory(Intent.CATEGORY_HOME);
-
-        ResolveInfo info = mContext.getPackageManager().resolveActivity(intent,
-                PackageManager.MATCH_DEFAULT_ONLY);
-        if (info != null && top.equals(info.activityInfo.packageName)) {
-            return true;
-        }
-
-        return false;
-    }
-}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 66007e5..7530229 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -165,7 +165,8 @@
     int getTaskForActivity(in IBinder token, in boolean onlyRoot);
     /** Finish all activities that were started for result from the specified activity. */
     void finishSubActivity(in IBinder token, in String resultWho, int requestCode);
-    ParceledListSlice getRecentTasks(int maxNum, int flags, int userId);
+    ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags,
+            int userId);
     boolean willActivityBeVisible(in IBinder token);
     void setRequestedOrientation(in IBinder token, int requestedOrientation);
     int getRequestedOrientation(in IBinder token);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index fe89366..d442f5f 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1567,8 +1567,20 @@
         }
     }
 
-    /** @hide */
-    public void setNotificationListenerAccessGranted(ComponentName listener, boolean granted) {
+    /**
+     * Grants/revokes Notification Listener access to the given component for current user.
+     * To grant access for a particular user, obtain this service by using the {@link Context}
+     * provided by {@link Context#createPackageContextAsUser}
+     *
+     * @param listener Name of component to grant/revoke access
+     * @param granted Grant/revoke access
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS)
+    public void setNotificationListenerAccessGranted(
+            @NonNull ComponentName listener, boolean granted) {
         INotificationManager service = getService();
         try {
             service.setNotificationListenerAccessGranted(listener, granted);
@@ -1610,6 +1622,21 @@
         }
     }
 
+    /**
+     * Gets the list of enabled notification listener components for current user.
+     * To query for a particular user, obtain this service by using the {@link Context}
+     * provided by {@link Context#createPackageContextAsUser}
+     *
+     * @return the list of {@link ComponentName}s of the notification listeners
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS)
+    public @NonNull List<ComponentName> getEnabledNotificationListeners() {
+        return getEnabledNotificationListeners(mContext.getUserId());
+    }
+
     /** @hide */
     public List<ComponentName> getEnabledNotificationListeners(int userId) {
         INotificationManager service = getService();
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index e8937a8..8054cdb 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -363,6 +363,7 @@
      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
      * supplied.
      */
+    @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
     public static PendingIntent getActivity(Context context, int requestCode,
             Intent intent, @Flags int flags) {
         return getActivity(context, requestCode, intent, flags, null);
@@ -489,6 +490,7 @@
      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
      * supplied.
      */
+    @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
     public static PendingIntent getActivities(Context context, int requestCode,
             @NonNull Intent[] intents, @Flags int flags) {
         return getActivities(context, requestCode, intents, flags, null);
@@ -611,6 +613,7 @@
      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
      * supplied.
      */
+    @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
     public static PendingIntent getBroadcast(Context context, int requestCode,
             Intent intent, @Flags int flags) {
         return getBroadcastAsUser(context, requestCode, intent, flags, context.getUser());
diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java
index b99b327..e238046 100644
--- a/core/java/android/app/TaskStackBuilder.java
+++ b/core/java/android/app/TaskStackBuilder.java
@@ -264,6 +264,7 @@
      *
      * @return The obtained PendingIntent
      */
+    @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
     public PendingIntent getPendingIntent(int requestCode, @PendingIntent.Flags int flags,
             Bundle options) {
         if (mIntents.isEmpty()) {
@@ -278,6 +279,7 @@
     /**
      * @hide
      */
+    @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
     public PendingIntent getPendingIntent(int requestCode, int flags, Bundle options,
             UserHandle user) {
         if (mIntents.isEmpty()) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2f1254f..a14e21b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2744,7 +2744,6 @@
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent by the system.
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
@@ -2755,13 +2754,13 @@
      * <ul>
      * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. </li>
      * <li> {@link #EXTRA_PACKAGE_NAME} containing the package name. </li>
-     * <li> {@link #EXTRA_REASON} containing the integer indicating the reason for the state change,
+     * <li> {@link #EXTRA_UNSTARTABLE_REASON} containing the integer indicating the reason for
+     * the state change,
      * @see PackageManager.UnstartableReason
      * </li>
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent by the system.
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_UNSTARTABLE =
@@ -2776,7 +2775,6 @@
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent by the system.
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_FULLY_LOADED =
@@ -6015,6 +6013,13 @@
      */
     public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID";
 
+    /**
+     * Intent extra: the reason that the package associated with this intent has become unstartable.
+     *
+     * <p>Type: String
+     */
+    public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1a992f5..32ae105 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3790,8 +3790,8 @@
      * @hide
      */
     @IntDef({UNSTARTABLE_REASON_UNKNOWN,
-            UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
-            UNSTARTABLE_REASON_DATALOADER_STORAGE
+            UNSTARTABLE_REASON_CONNECTION_ERROR,
+            UNSTARTABLE_REASON_INSUFFICIENT_STORAGE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface UnstartableReason {}
@@ -3800,23 +3800,20 @@
      * Unstartable state with no root cause specified. E.g., data loader seeing missing pages but
      * unclear about the cause. This corresponds to a generic alert window shown to the user when
      * the user attempts to launch the app.
-     * @hide
      */
     public static final int UNSTARTABLE_REASON_UNKNOWN = 0;
 
     /**
-     * Unstartable state after hint from dataloader of issues with the transport layer.
-     * This corresponds to an alert window shown to the user indicating network errors.
-     * @hide
+     * Unstartable state due to connection issues that interrupt package loading.
+     * This corresponds to an alert window shown to the user indicating connection errors.
      */
-    public static final int UNSTARTABLE_REASON_DATALOADER_TRANSPORT = 1;
+    public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1;
 
     /**
      * Unstartable state after encountering storage limitations.
      * This corresponds to an alert window indicating limited storage.
-     * @hide
      */
-    public static final int UNSTARTABLE_REASON_DATALOADER_STORAGE = 2;
+    public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2;
 
     /** {@hide} */
     public int getUserId() {
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 35ef53b..25c749b 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -35,6 +35,8 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A class that contains biometric utilities. For authentication, see {@link BiometricPrompt}.
@@ -199,13 +201,24 @@
     }
 
     /**
+     * @return A list of {@link SensorProperties}
+     * @hide
+     */
+    @TestApi
+    @NonNull
+    @RequiresPermission(TEST_BIOMETRIC)
+    public List<SensorProperties> getSensorProperties() {
+        return new ArrayList<>(); // TODO(169459906)
+    }
+
+    /**
      * Retrieves a test session for BiometricManager/BiometricPrompt.
      * @hide
      */
     @TestApi
     @NonNull
     @RequiresPermission(TEST_BIOMETRIC)
-    public BiometricTestSession getTestSession() {
+    public BiometricTestSession createTestSession(int sensorId) {
         return null; // TODO(169459906)
     }
 
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
index 719efa8..4c7aa27 100644
--- a/core/java/android/hardware/biometrics/BiometricTestSession.java
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -23,10 +23,7 @@
 import android.annotation.TestApi;
 import android.content.Context;
 import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
+import android.util.ArraySet;
 
 /**
  * Common set of interfaces to test biometric-related APIs, including {@link BiometricPrompt} and
@@ -35,37 +32,20 @@
  */
 @TestApi
 public class BiometricTestSession implements AutoCloseable {
-
-    private static final String TAG = "TestManager";
-
     private final Context mContext;
-    private final ITestService mTestService;
+    private final ITestSession mTestSession;
+
+    // Keep track of users that were tested, which need to be cleaned up when finishing.
+    private final ArraySet<Integer> mTestedUsers;
 
     /**
      * @hide
      */
-    public BiometricTestSession(@NonNull Context context, @NonNull ITestService testService) {
+    public BiometricTestSession(@NonNull Context context, @NonNull ITestSession testSession) {
         mContext = context;
-        mTestService = testService;
-    }
-
-    /**
-     * @return A list of {@link SensorProperties}
-     */
-    @NonNull
-    @RequiresPermission(TEST_BIOMETRIC)
-    public List<SensorProperties> getSensorProperties() {
-        try {
-            final List<SensorPropertiesInternal> internalProps =
-                    mTestService.getSensorPropertiesInternal(mContext.getOpPackageName());
-            final List<SensorProperties> props = new ArrayList<>();
-            for (SensorPropertiesInternal internalProp : internalProps) {
-                props.add(new SensorProperties(internalProp.sensorId, internalProp.sensorStrength));
-            }
-            return props;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        mTestSession = testSession;
+        mTestedUsers = new ArraySet<>();
+        enableTestHal(true);
     }
 
     /**
@@ -75,105 +55,100 @@
      * secure pathways such as HAT/Keystore are not testable, since they depend on the TEE or its
      * equivalent for the secret key.
      *
-     * @param sensorId Sensor that this command applies to.
      * @param enableTestHal If true, enable testing with a fake HAL instead of the real HAL.
      */
     @RequiresPermission(TEST_BIOMETRIC)
-    public void enableTestHal(int sensorId, boolean enableTestHal) {
+    private void enableTestHal(boolean enableTestHal) {
         try {
-            mTestService.enableTestHal(sensorId, enableTestHal);
+            mTestSession.enableTestHal(enableTestHal);
         } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
     /**
      * Starts the enrollment process. This should generally be used when the test HAL is enabled.
      *
-     * @param sensorId Sensor that this command applies to.
      * @param userId User that this command applies to.
      */
     @RequiresPermission(TEST_BIOMETRIC)
-    public void enrollStart(int sensorId, int userId) {
+    public void startEnroll(int userId) {
         try {
-            mTestService.enrollStart(sensorId, userId);
+            mTestedUsers.add(userId);
+            mTestSession.startEnroll(userId);
         } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
     /**
      * Finishes the enrollment process. Simulates the HAL's callback.
      *
-     * @param sensorId Sensor that this command applies to.
      * @param userId User that this command applies to.
      */
     @RequiresPermission(TEST_BIOMETRIC)
-    public void enrollFinish(int sensorId, int userId) {
+    public void finishEnroll(int userId) {
         try {
-            mTestService.enrollFinish(sensorId, userId);
+            mTestedUsers.add(userId);
+            mTestSession.finishEnroll(userId);
         } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
     /**
      * Simulates a successful authentication, but does not provide a valid HAT.
      *
-     * @param sensorId Sensor that this command applies to.
      * @param userId User that this command applies to.
      */
     @RequiresPermission(TEST_BIOMETRIC)
-    public void authenticateSuccess(int sensorId, int userId) {
+    public void acceptAuthentication(int userId) {
         try {
-            mTestService.authenticateSuccess(sensorId, userId);
+            mTestSession.acceptAuthentication(userId);
         } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
     /**
      * Simulates a rejected attempt.
      *
-     * @param sensorId Sensor that this command applies to.
      * @param userId User that this command applies to.
      */
     @RequiresPermission(TEST_BIOMETRIC)
-    public void authenticateReject(int sensorId, int userId) {
+    public void rejectAuthentication(int userId) {
         try {
-            mTestService.authenticateReject(sensorId, userId);
+            mTestSession.rejectAuthentication(userId);
         } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
     /**
      * Simulates an acquired message from the HAL.
      *
-     * @param sensorId Sensor that this command applies to.
      * @param userId User that this command applies to.
      */
     @RequiresPermission(TEST_BIOMETRIC)
-    public void notifyAcquired(int sensorId, int userId) {
+    public void notifyAcquired(int userId) {
         try {
-            mTestService.notifyAcquired(sensorId, userId);
+            mTestSession.notifyAcquired(userId);
         } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
     /**
      * Simulates an error message from the HAL.
      *
-     * @param sensorId Sensor that this command applies to.
      * @param userId User that this command applies to.
      */
     @RequiresPermission(TEST_BIOMETRIC)
-    public void notifyError(int sensorId, int userId) {
+    public void notifyError(int userId) {
         try {
-            mTestService.notifyError(sensorId, userId);
+            mTestSession.notifyError(userId);
         } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -182,21 +157,24 @@
      * that isn't known by both sides are deleted. This should generally be used when the test
      * HAL is disabled (e.g. to clean up after a test).
      *
-     * @param sensorId Sensor that this command applies to.
      * @param userId User that this command applies to.
      */
     @RequiresPermission(TEST_BIOMETRIC)
-    public void internalCleanup(int sensorId, int userId) {
+    public void cleanupInternalState(int userId) {
         try {
-            mTestService.internalCleanup(sensorId, userId);
+            mTestSession.cleanupInternalState(userId);
         } catch (RemoteException e) {
-            Log.e(TAG, "Remote exception", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
     @Override
     @RequiresPermission(TEST_BIOMETRIC)
     public void close() {
+        for (int user : mTestedUsers) {
+            cleanupInternalState(user);
+        }
 
+        enableTestHal(false);
     }
 }
diff --git a/core/java/android/hardware/biometrics/ITestService.aidl b/core/java/android/hardware/biometrics/ITestSession.aidl
similarity index 75%
rename from core/java/android/hardware/biometrics/ITestService.aidl
rename to core/java/android/hardware/biometrics/ITestSession.aidl
index 6373132..5677f65 100644
--- a/core/java/android/hardware/biometrics/ITestService.aidl
+++ b/core/java/android/hardware/biometrics/ITestSession.aidl
@@ -21,37 +21,34 @@
  * A test service for FingerprintManager and BiometricPrompt.
  * @hide
  */
-interface ITestService {
-    // Returns a list of sensor properties supported by the interface.
-    List<SensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);
-
+interface ITestSession {
     // Switches the specified sensor to use a test HAL. In this mode, the framework will not invoke
     // any methods on the real HAL implementation. This allows the framework to test a substantial
     // portion of the framework code that would otherwise require human interaction. Note that
     // secure pathways such as HAT/Keystore are not testable, since they depend on the TEE or its
     // equivalent for the secret key.
-    void enableTestHal(int sensorId, boolean enableTestHal);
+    void enableTestHal(boolean enableTestHal);
 
     // Starts the enrollment process. This should generally be used when the test HAL is enabled.
-    void enrollStart(int sensorId, int userId);
+    void startEnroll(int userId);
 
     // Finishes the enrollment process. Simulates the HAL's callback.
-    void enrollFinish(int sensorId, int userId);
+    void finishEnroll(int userId);
 
     // Simulates a successful authentication, but does not provide a valid HAT.
-    void authenticateSuccess(int sensorId, int userId);
+    void acceptAuthentication(int userId);
 
     // Simulates a rejected attempt.
-    void authenticateReject(int sensorId, int userId);
+    void rejectAuthentication(int userId);
 
     // Simulates an acquired message from the HAL.
-    void notifyAcquired(int sensorId, int userId);
+    void notifyAcquired(int userId);
 
     // Simulates an error message from the HAL.
-    void notifyError(int sensorId, int userId);
+    void notifyError(int userId);
 
     // Matches the framework's cached enrollments against the HAL's enrollments. Any enrollment
     // that isn't known by both sides are deleted. This should generally be used when the test
     // HAL is disabled (e.g. to clean up after a test).
-    void internalCleanup(int sensorId, int userId);
+    void cleanupInternalState(int userId);
 }
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index b35a68f..c5f8dac 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -39,6 +39,7 @@
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.BiometricTestSession;
 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.SensorProperties;
 import android.os.Binder;
 import android.os.CancellationSignal;
 import android.os.CancellationSignal.OnCancelListener;
@@ -97,6 +98,24 @@
     private Fingerprint mRemovalFingerprint;
     private Handler mHandler;
 
+
+    /**
+     * Retrieves a list of properties for all fingerprint sensors on the device.
+     * @hide
+     */
+    @TestApi
+    @NonNull
+    @RequiresPermission(TEST_BIOMETRIC)
+    public List<SensorProperties> getSensorProperties() {
+        final List<SensorProperties> properties = new ArrayList<>();
+        final List<FingerprintSensorPropertiesInternal> internalProperties
+                = getSensorPropertiesInternal();
+        for (FingerprintSensorPropertiesInternal internalProp : internalProperties) {
+            properties.add(FingerprintSensorProperties.from(internalProp));
+        }
+        return properties;
+    }
+
     /**
      * Retrieves a test session for FingerprintManager.
      * @hide
@@ -104,10 +123,10 @@
     @TestApi
     @NonNull
     @RequiresPermission(TEST_BIOMETRIC)
-    public BiometricTestSession getTestSession() {
+    public BiometricTestSession createTestSession(int sensorId) {
         try {
             return new BiometricTestSession(mContext,
-                    mService.getTestService(mContext.getOpPackageName()));
+                    mService.createTestSession(sensorId, mContext.getOpPackageName()));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -878,21 +897,6 @@
     }
 
     /**
-     * Retrieves a list of properties for all fingerprint sensors on the device.
-     * @hide
-     */
-    @NonNull
-    public List<FingerprintSensorProperties> getSensorProperties() {
-        final List<FingerprintSensorProperties> properties = new ArrayList<>();
-        final List<FingerprintSensorPropertiesInternal> internalProperties
-                = getSensorPropertiesInternal();
-        for (FingerprintSensorPropertiesInternal internalProp : internalProperties) {
-            properties.add(FingerprintSensorProperties.from(internalProp));
-        }
-        return properties;
-    }
-
-    /**
      * Get statically configured sensor properties.
      * @hide
      */
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index e8ca590..cc086cf 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -17,7 +17,7 @@
 
 import android.hardware.biometrics.IBiometricSensorReceiver;
 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
-import android.hardware.biometrics.ITestService;
+import android.hardware.biometrics.ITestSession;
 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
 import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -32,8 +32,8 @@
  */
 interface IFingerprintService {
 
-    // Retrieves a test service
-    ITestService getTestService(String opPackageName);
+    // Creates a test session with the specified sensorId
+    ITestSession createTestSession(int sensorId, String opPackageName);
 
     // Retrieve static sensor properties for all fingerprint sensors
     List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.java b/core/java/android/os/connectivity/CellularBatteryStats.java
index 121fd33..fc17002 100644
--- a/core/java/android/os/connectivity/CellularBatteryStats.java
+++ b/core/java/android/os/connectivity/CellularBatteryStats.java
@@ -109,7 +109,7 @@
                         CellSignalStrength.getNumSignalStrengthLevels()));
         mTxTimeMs = Arrays.copyOfRange(
                 txTimeMs, 0,
-                Math.min(txTimeMs.length, ModemActivityInfo.TX_POWER_LEVELS));
+                Math.min(txTimeMs.length, ModemActivityInfo.getNumTxPowerLevels()));
         mMonitoredRailChargeConsumedMaMs = monitoredRailChargeConsumedMaMs;
     }
 
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 0f46ffc..4d1337b 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -227,9 +227,6 @@
 
         SurfaceControl mSurfaceControl = new SurfaceControl();
 
-        // Unused relayout out-param
-        SurfaceControl mTmpSurfaceControl = new SurfaceControl();
-
         final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
             {
                 mRequestedFormat = PixelFormat.RGBX_8888;
@@ -905,7 +902,7 @@
                     final int relayoutResult = mSession.relayout(
                             mWindow, mLayout, mWidth, mHeight,
                             View.VISIBLE, 0, -1, mWinFrames, mMergedConfiguration, mSurfaceControl,
-                            mInsetsState, mTempControls, mSurfaceSize, mTmpSurfaceControl);
+                            mInsetsState, mTempControls, mSurfaceSize);
                     if (mSurfaceControl.isValid()) {
                         mSurfaceHolder.mSurface.copyFrom(mSurfaceControl);
                     }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 69a5faf..910fd90 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -98,9 +98,6 @@
      * @param outSurface Object in which is placed the new display surface.
      * @param insetsState The current insets state in the system.
      * @param outSurfaceSize The width and height of the surface control
-     * @param outBlastSurfaceControl A BLAST SurfaceControl allocated by the WindowManager
-     * the SurfaceControl willl be managed by the client side, but the WindowManager
-     * may use it as a deferTransaction barrier.
      *
      * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
      * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
@@ -110,7 +107,7 @@
             int flags, long frameNumber, out ClientWindowFrames outFrames,
             out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
             out InsetsState insetsState, out InsetsSourceControl[] activeControls,
-            out Point outSurfaceSize, out SurfaceControl outBlastSurfaceControl);
+            out Point outSurfaceSize);
 
     /*
      * Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/RemoteAccessibilityController.java b/core/java/android/view/RemoteAccessibilityController.java
new file mode 100644
index 0000000..bc0fab1b
--- /dev/null
+++ b/core/java/android/view/RemoteAccessibilityController.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2020 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 android.view;
+
+import android.graphics.Matrix;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.accessibility.IAccessibilityEmbeddedConnection;
+
+class RemoteAccessibilityController {
+    private static final String TAG = "RemoteAccessibilityController";
+    private int mHostId;
+    private RemoteAccessibilityEmbeddedConnection mConnectionWrapper;
+    private Matrix mScreenMatrixForEmbeddedHierarchy = new Matrix();
+    private final float[] mMatrixValues = new float[9];
+    private View mHostView;
+
+    RemoteAccessibilityController(View v) {
+        mHostView = v;
+    }
+
+    private void runOnUiThread(Runnable runnable) {
+        final Handler h = mHostView.getHandler();
+        if (h != null && h.getLooper() != Looper.myLooper()) {
+            h.post(runnable);
+        } else {
+            runnable.run();
+        }
+    }
+
+    void assosciateHierarchy(IAccessibilityEmbeddedConnection connection,
+        IBinder leashToken, int hostId) {
+        mHostId = hostId;
+
+        try {
+            leashToken = connection.associateEmbeddedHierarchy(
+                leashToken, mHostId);
+            setRemoteAccessibilityEmbeddedConnection(connection, leashToken);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Error in associateEmbeddedHierarchy " + e);
+        }
+    }
+
+    void disassosciateHierarchy() {
+        setRemoteAccessibilityEmbeddedConnection(null, null);
+    }
+
+    boolean alreadyAssociated(IAccessibilityEmbeddedConnection connection) {
+        if (mConnectionWrapper == null) {
+            return false;
+        }
+        return mConnectionWrapper.mConnection.equals(connection);
+    }
+
+    boolean connected() {
+      return mConnectionWrapper != null;
+    }
+
+    IBinder getLeashToken() {
+        return mConnectionWrapper.getLeashToken();
+    }
+
+    /**
+     * Wrapper of accessibility embedded connection for embedded view hierarchy.
+     */
+    private final class RemoteAccessibilityEmbeddedConnection implements IBinder.DeathRecipient {
+        private final IAccessibilityEmbeddedConnection mConnection;
+        private final IBinder mLeashToken;
+
+        RemoteAccessibilityEmbeddedConnection(IAccessibilityEmbeddedConnection connection,
+                IBinder leashToken) {
+            mConnection = connection;
+            mLeashToken = leashToken;
+        }
+
+        IAccessibilityEmbeddedConnection getConnection() {
+            return mConnection;
+        }
+
+        IBinder getLeashToken() {
+            return mLeashToken;
+        }
+
+        void linkToDeath() throws RemoteException {
+            mConnection.asBinder().linkToDeath(this, 0);
+        }
+
+        void unlinkToDeath() {
+            mConnection.asBinder().unlinkToDeath(this, 0);
+        }
+
+        @Override
+        public void binderDied() {
+            unlinkToDeath();
+            runOnUiThread(() -> {
+                if (mConnectionWrapper == this) {
+                    mConnectionWrapper = null;
+                }
+            });
+        }
+    }
+
+    private void setRemoteAccessibilityEmbeddedConnection(
+          IAccessibilityEmbeddedConnection connection, IBinder leashToken) {
+        try {
+            if (mConnectionWrapper != null) {
+                mConnectionWrapper.getConnection()
+                    .disassociateEmbeddedHierarchy();
+                mConnectionWrapper.unlinkToDeath();
+                mConnectionWrapper = null;
+            }
+            if (connection != null && leashToken != null) {
+                mConnectionWrapper =
+                    new RemoteAccessibilityEmbeddedConnection(connection, leashToken);
+                mConnectionWrapper.linkToDeath();
+            }
+        } catch (RemoteException e) {
+            Log.d(TAG, "Error while setRemoteEmbeddedConnection " + e);
+        }
+    }
+
+    private RemoteAccessibilityEmbeddedConnection getRemoteAccessibilityEmbeddedConnection() {
+        return mConnectionWrapper;
+    }
+
+    void setScreenMatrix(Matrix m) {
+        // If the screen matrix is identity or doesn't change, do nothing.
+        if (m.isIdentity() || m.equals(mScreenMatrixForEmbeddedHierarchy)) {
+            return;
+        }
+
+        try {
+            final RemoteAccessibilityEmbeddedConnection wrapper =
+                    getRemoteAccessibilityEmbeddedConnection();
+            if (wrapper == null) {
+                return;
+            }
+            m.getValues(mMatrixValues);
+            wrapper.getConnection().setScreenMatrix(mMatrixValues);
+            mScreenMatrixForEmbeddedHierarchy.set(m);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Error while setScreenMatrix " + e);
+        }
+    }
+
+
+
+
+
+
+}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 78c71b8..7b6a4f8 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -41,7 +41,6 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.RemoteException;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.AttributeSet;
@@ -225,13 +224,12 @@
 
     private SurfaceControl.Transaction mRtTransaction = new SurfaceControl.Transaction();
     private SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
-    private int mParentSurfaceGenerationId;
+    private int mParentSurfaceSequenceId;
 
-    private RemoteAccessibilityEmbeddedConnection mRemoteAccessibilityEmbeddedConnection;
+    private RemoteAccessibilityController mRemoteAccessibilityController =
+        new RemoteAccessibilityController(this);
 
-    private final Matrix mScreenMatrixForEmbeddedHierarchy = new Matrix();
     private final Matrix mTmpMatrix = new Matrix();
-    private final float[] mMatrixValues = new float[9];
 
     SurfaceControlViewHost.SurfacePackage mSurfacePackage;
 
@@ -467,7 +465,7 @@
                                 Transaction t = new SurfaceControl.Transaction();
                                 t.setAlpha(mSurfaceControl, alpha);
                                 t.deferTransactionUntil(mSurfaceControl,
-                                        viewRoot.getRenderSurfaceControl(), frame);
+                                        viewRoot.getSurfaceControl(), frame);
                                 t.apply();
                             }
                         }
@@ -827,7 +825,7 @@
                         final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
                         updateRelativeZ(t);
                         t.deferTransactionUntil(mSurfaceControl,
-                                viewRoot.getRenderSurfaceControl(), frame);
+                                viewRoot.getSurfaceControl(), frame);
                         t.apply();
                     }
                 }
@@ -927,6 +925,103 @@
         }
     }
 
+    private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
+        boolean creating, boolean sizeChanged, boolean needBLASTSync) {
+        boolean realSizeChanged = false;
+
+        mSurfaceLock.lock();
+        try {
+            mDrawingStopped = !mVisible;
+
+            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+                    + "Cur surface: " + mSurface);
+
+            // If we are creating the surface control or the parent surface has not
+            // changed, then set relative z. Otherwise allow the parent
+            // SurfaceChangedCallback to update the relative z. This is needed so that
+            // we do not change the relative z before the server is ready to swap the
+            // parent surface.
+            if (creating || (mParentSurfaceSequenceId == viewRoot.getSurfaceSequenceId())) {
+                updateRelativeZ(mTmpTransaction);
+            }
+            mParentSurfaceSequenceId = viewRoot.getSurfaceSequenceId();
+
+            if (mViewVisibility) {
+                mTmpTransaction.show(mSurfaceControl);
+            } else {
+                mTmpTransaction.hide(mSurfaceControl);
+            }
+
+            if (mSurfacePackage != null) {
+                reparentSurfacePackage(mTmpTransaction, mSurfacePackage);
+            }
+
+            updateBackgroundVisibility(mTmpTransaction);
+            updateBackgroundColor(mTmpTransaction);
+            if (mUseAlpha) {
+                float alpha = getFixedAlpha();
+                mTmpTransaction.setAlpha(mSurfaceControl, alpha);
+                mSurfaceAlpha = alpha;
+            }
+
+            // While creating the surface, we will set it's initial
+            // geometry. Outside of that though, we should generally
+            // leave it to the RenderThread.
+            //
+            // There is one more case when the buffer size changes we aren't yet
+            // prepared to sync (as even following the transaction applying
+            // we still need to latch a buffer).
+            // b/28866173
+            if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
+                onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
+                        mScreenRect.left, /*positionLeft*/
+                        mScreenRect.top /*positionTop*/ ,
+                        mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
+                        mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
+
+                // Set a window crop when creating the surface or changing its size to
+                // crop the buffer to the surface size since the buffer producer may
+                // use SCALING_MODE_SCALE and submit a larger size than the surface
+                // size.
+                if (mClipSurfaceToBounds && mClipBounds != null) {
+                    mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
+                } else {
+                    mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
+                            mSurfaceHeight);
+                }
+            } else if (needBLASTSync) {
+                viewRoot.setUseBLASTSyncTransaction();
+            }
+            mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
+            if (sizeChanged && !creating) {
+                setBufferSize(mTmpTransaction);
+            }
+
+            mTmpTransaction.apply();
+            updateEmbeddedAccessibilityMatrix();
+
+            mSurfaceFrame.left = 0;
+            mSurfaceFrame.top = 0;
+            if (translator == null) {
+                mSurfaceFrame.right = mSurfaceWidth;
+                mSurfaceFrame.bottom = mSurfaceHeight;
+            } else {
+                float appInvertedScale = translator.applicationInvertedScale;
+                mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f);
+                mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f);
+            }
+            final int surfaceWidth = mSurfaceFrame.right;
+            final int surfaceHeight = mSurfaceFrame.bottom;
+            realSizeChanged = mLastSurfaceWidth != surfaceWidth
+                    || mLastSurfaceHeight != surfaceHeight;
+            mLastSurfaceWidth = surfaceWidth;
+            mLastSurfaceHeight = surfaceHeight;
+        } finally {
+            mSurfaceLock.unlock();
+        }
+        return realSizeChanged;
+    }
+
     /** @hide */
     protected void updateSurface() {
         if (!mHaveFrame) {
@@ -965,7 +1060,6 @@
                 && mRequestedVisible;
         final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
         final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility;
-        boolean redrawNeeded = false;
         getLocationInSurface(mLocation);
         final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
             || mWindowSpaceTop != mLocation[1];
@@ -988,7 +1082,7 @@
                     + " top=" + (mWindowSpaceTop != mLocation[1]));
 
             try {
-                final boolean visible = mVisible = mRequestedVisible;
+                mVisible = mRequestedVisible;
                 mWindowSpaceLeft = mLocation[0];
                 mWindowSpaceTop = mLocation[1];
                 mSurfaceWidth = myWidth;
@@ -1014,119 +1108,26 @@
                     return;
                 }
 
-                boolean realSizeChanged = false;
-
-                mSurfaceLock.lock();
-                try {
-                    mDrawingStopped = !visible;
-
-                    if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
-                            + "Cur surface: " + mSurface);
-
-                    // If we are creating the surface control or the parent surface has not
-                    // changed, then set relative z. Otherwise allow the parent
-                    // SurfaceChangedCallback to update the relative z. This is needed so that
-                    // we do not change the relative z before the server is ready to swap the
-                    // parent surface.
-                    if (creating || (mParentSurfaceGenerationId
-                            == viewRoot.mSurface.getGenerationId())) {
-                        updateRelativeZ(mTmpTransaction);
-                    }
-                    mParentSurfaceGenerationId = viewRoot.mSurface.getGenerationId();
-
-                    if (mViewVisibility) {
-                        mTmpTransaction.show(mSurfaceControl);
-                    } else {
-                        mTmpTransaction.hide(mSurfaceControl);
-                    }
-
-                    if (mSurfacePackage != null) {
-                        reparentSurfacePackage(mTmpTransaction, mSurfacePackage);
-                    }
-
-                    updateBackgroundVisibility(mTmpTransaction);
-                    updateBackgroundColor(mTmpTransaction);
-                    if (mUseAlpha) {
-                        mTmpTransaction.setAlpha(mSurfaceControl, alpha);
-                        mSurfaceAlpha = alpha;
-                    }
-
-                    // While creating the surface, we will set it's initial
-                    // geometry. Outside of that though, we should generally
-                    // leave it to the RenderThread.
-                    //
-                    // There is one more case when the buffer size changes we aren't yet
-                    // prepared to sync (as even following the transaction applying
-                    // we still need to latch a buffer).
-                    // b/28866173
-                    if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
-                        onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
-                                mScreenRect.left, /*positionLeft*/
-                                mScreenRect.top /*positionTop*/ ,
-                                mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
-                                mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
-
-                        // Set a window crop when creating the surface or changing its size to
-                        // crop the buffer to the surface size since the buffer producer may
-                        // use SCALING_MODE_SCALE and submit a larger size than the surface
-                        // size.
-                        if (mClipSurfaceToBounds && mClipBounds != null) {
-                            mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
-                        } else {
-                            mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
-                                    mSurfaceHeight);
-                        }
-                    } else if ((layoutSizeChanged || positionChanged || visibleChanged) &&
-                            viewRoot.useBLAST()) {
-                        viewRoot.setUseBLASTSyncTransaction();
-                    }
-                    mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
-                    if (sizeChanged && !creating) {
-                        setBufferSize(mTmpTransaction);
-                    }
-
-                    mTmpTransaction.apply();
-                    updateScreenMatrixForEmbeddedHierarchy();
-
-                    if (sizeChanged || creating) {
-                        redrawNeeded = true;
-                    }
-
-                    mSurfaceFrame.left = 0;
-                    mSurfaceFrame.top = 0;
-                    if (translator == null) {
-                        mSurfaceFrame.right = mSurfaceWidth;
-                        mSurfaceFrame.bottom = mSurfaceHeight;
-                    } else {
-                        float appInvertedScale = translator.applicationInvertedScale;
-                        mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f);
-                        mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f);
-                    }
-
-                    final int surfaceWidth = mSurfaceFrame.right;
-                    final int surfaceHeight = mSurfaceFrame.bottom;
-                    realSizeChanged = mLastSurfaceWidth != surfaceWidth
-                            || mLastSurfaceHeight != surfaceHeight;
-                    mLastSurfaceWidth = surfaceWidth;
-                    mLastSurfaceHeight = surfaceHeight;
-                } finally {
-                    mSurfaceLock.unlock();
-                }
+                final boolean needBLASTSync =
+                    (layoutSizeChanged || positionChanged || visibleChanged) &&
+                        viewRoot.useBLAST();
+                final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
+                    translator, creating, sizeChanged, needBLASTSync);
+                final boolean redrawNeeded = sizeChanged || creating ||
+                    (mVisible && !mDrawFinished);
 
                 try {
-                    redrawNeeded |= visible && !mDrawFinished;
-
                     SurfaceHolder.Callback[] callbacks = null;
 
                     final boolean surfaceChanged = creating;
-                    if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
+                    if (mSurfaceCreated && (surfaceChanged || (!mVisible && visibleChanged))) {
                         mSurfaceCreated = false;
                         notifySurfaceDestroyed();
                     }
 
                     copySurface(creating /* surfaceControlCreated */, sizeChanged);
 
-                    if (visible && mSurface.isValid()) {
+                    if (mVisible && mSurface.isValid()) {
                         if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
                             mSurfaceCreated = true;
                             mIsCreating = true;
@@ -1352,7 +1353,7 @@
             Rect position, long frameNumber) {
         final ViewRootImpl viewRoot = getViewRootImpl();
         if (frameNumber > 0 && viewRoot != null && !viewRoot.useBLAST()) {
-            t.deferTransactionUntil(surface, viewRoot.getRenderSurfaceControl(),
+            t.deferTransactionUntil(surface, viewRoot.getSurfaceControl(),
                     frameNumber);
         }
 
@@ -1470,7 +1471,7 @@
                 } else {
                     if (frameNumber > 0 && viewRoot != null && viewRoot.mSurface.isValid()) {
                         mRtTransaction.deferTransactionUntil(mSurfaceControl,
-                                viewRoot.getRenderSurfaceControl(), frameNumber);
+                                viewRoot.getSurfaceControl(), frameNumber);
                     }
                     mRtTransaction.hide(mSurfaceControl);
                     if (mRtReleaseSurfaces) {
@@ -1754,7 +1755,7 @@
     @Override
     public void surfaceDestroyed() {
         setWindowStopped(true);
-        setRemoteAccessibilityEmbeddedConnection(null, null);
+        mRemoteAccessibilityController.disassosciateHierarchy();
     }
 
     /**
@@ -1834,14 +1835,12 @@
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        final RemoteAccessibilityEmbeddedConnection wrapper =
-                getRemoteAccessibilityEmbeddedConnection();
-        if (wrapper == null) {
+        if (!mRemoteAccessibilityController.connected()) {
             return;
         }
         // Add a leashed child when this SurfaceView embeds another view hierarchy. Getting this
         // leashed child would return the root node in the embedded hierarchy
-        info.addChild(wrapper.getLeashToken());
+        info.addChild(mRemoteAccessibilityController.getLeashToken());
     }
 
     @Override
@@ -1850,7 +1849,7 @@
         // If developers explicitly set the important mode for it, don't change the mode.
         // Only change the mode to important when this SurfaceView isn't explicitly set and has
         // an embedded hierarchy.
-        if (mRemoteAccessibilityEmbeddedConnection == null
+        if (!mRemoteAccessibilityController.connected()
                 || mode != IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             return mode;
         }
@@ -1859,74 +1858,13 @@
 
     private void initEmbeddedHierarchyForAccessibility(SurfaceControlViewHost.SurfacePackage p) {
         final IAccessibilityEmbeddedConnection connection = p.getAccessibilityEmbeddedConnection();
-        final RemoteAccessibilityEmbeddedConnection wrapper =
-                getRemoteAccessibilityEmbeddedConnection();
-
-        // Do nothing if package is embedding the same view hierarchy.
-        if (wrapper != null && wrapper.getConnection().equals(connection)) {
+        if (mRemoteAccessibilityController.alreadyAssociated(connection)) {
             return;
         }
+        mRemoteAccessibilityController.assosciateHierarchy(connection,
+            getViewRootImpl().mLeashToken, getAccessibilityViewId());
 
-        // If this SurfaceView embeds a different view hierarchy, unlink the previous one first.
-        setRemoteAccessibilityEmbeddedConnection(null, null);
-
-        try {
-            final IBinder leashToken = connection.associateEmbeddedHierarchy(
-                    getViewRootImpl().mLeashToken, getAccessibilityViewId());
-            setRemoteAccessibilityEmbeddedConnection(connection, leashToken);
-        } catch (RemoteException e) {
-            Log.d(TAG, "Error while associateEmbeddedHierarchy " + e);
-        }
-        updateScreenMatrixForEmbeddedHierarchy();
-    }
-
-    private void setRemoteAccessibilityEmbeddedConnection(
-            IAccessibilityEmbeddedConnection connection, IBinder leashToken) {
-        try {
-            if (mRemoteAccessibilityEmbeddedConnection != null) {
-                mRemoteAccessibilityEmbeddedConnection.getConnection()
-                        .disassociateEmbeddedHierarchy();
-                mRemoteAccessibilityEmbeddedConnection.unlinkToDeath();
-                mRemoteAccessibilityEmbeddedConnection = null;
-            }
-            if (connection != null && leashToken != null) {
-                mRemoteAccessibilityEmbeddedConnection =
-                        new RemoteAccessibilityEmbeddedConnection(connection, leashToken);
-                mRemoteAccessibilityEmbeddedConnection.linkToDeath();
-            }
-        } catch (RemoteException e) {
-            Log.d(TAG, "Error while setRemoteEmbeddedConnection " + e);
-        }
-    }
-
-    private RemoteAccessibilityEmbeddedConnection getRemoteAccessibilityEmbeddedConnection() {
-        return mRemoteAccessibilityEmbeddedConnection;
-    }
-
-    private void updateScreenMatrixForEmbeddedHierarchy() {
-        getBoundsOnScreen(mTmpRect);
-        mTmpMatrix.reset();
-        mTmpMatrix.setTranslate(mTmpRect.left, mTmpRect.top);
-        mTmpMatrix.postScale(mScreenRect.width() / (float) mSurfaceWidth,
-                mScreenRect.height() / (float) mSurfaceHeight);
-
-        // If the screen matrix is identity or doesn't change, do nothing.
-        if (mTmpMatrix.isIdentity() || mTmpMatrix.equals(mScreenMatrixForEmbeddedHierarchy)) {
-            return;
-        }
-
-        try {
-            final RemoteAccessibilityEmbeddedConnection wrapper =
-                    getRemoteAccessibilityEmbeddedConnection();
-            if (wrapper == null) {
-                return;
-            }
-            mTmpMatrix.getValues(mMatrixValues);
-            wrapper.getConnection().setScreenMatrix(mMatrixValues);
-            mScreenMatrixForEmbeddedHierarchy.set(mTmpMatrix);
-        } catch (RemoteException e) {
-            Log.d(TAG, "Error while setScreenMatrix " + e);
-        }
+        updateEmbeddedAccessibilityMatrix();
     }
 
     private void notifySurfaceDestroyed() {
@@ -1954,6 +1892,18 @@
         }
     }
 
+    void updateEmbeddedAccessibilityMatrix() {
+        if (!mRemoteAccessibilityController.connected()) {
+            return;
+        }
+        getBoundsOnScreen(mTmpRect);
+        mTmpMatrix.reset();
+        mTmpMatrix.setTranslate(mTmpRect.left, mTmpRect.top);
+        mTmpMatrix.postScale(mScreenRect.width() / (float) mSurfaceWidth,
+                mScreenRect.height() / (float) mSurfaceHeight);
+        mRemoteAccessibilityController.setScreenMatrix(mTmpMatrix);
+    }
+
     @Override
     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
                                   @Nullable Rect previouslyFocusedRect) {
@@ -1970,44 +1920,4 @@
                     + "Exception requesting focus on embedded window", e);
         }
     }
-
-    /**
-     * Wrapper of accessibility embedded connection for embedded view hierarchy.
-     */
-    private final class RemoteAccessibilityEmbeddedConnection implements IBinder.DeathRecipient {
-        private final IAccessibilityEmbeddedConnection mConnection;
-        private final IBinder mLeashToken;
-
-        RemoteAccessibilityEmbeddedConnection(IAccessibilityEmbeddedConnection connection,
-                IBinder leashToken) {
-            mConnection = connection;
-            mLeashToken = leashToken;
-        }
-
-        IAccessibilityEmbeddedConnection getConnection() {
-            return mConnection;
-        }
-
-        IBinder getLeashToken() {
-            return mLeashToken;
-        }
-
-        void linkToDeath() throws RemoteException {
-            mConnection.asBinder().linkToDeath(this, 0);
-        }
-
-        void unlinkToDeath() {
-            mConnection.asBinder().unlinkToDeath(this, 0);
-        }
-
-        @Override
-        public void binderDied() {
-            unlinkToDeath();
-            runOnUiThread(() -> {
-                if (mRemoteAccessibilityEmbeddedConnection == this) {
-                    mRemoteAccessibilityEmbeddedConnection = null;
-                }
-            });
-        }
-    }
 }
diff --git a/core/java/android/view/SyncRtSurfaceTransactionApplier.java b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
index 062285f..bce78b5 100644
--- a/core/java/android/view/SyncRtSurfaceTransactionApplier.java
+++ b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
@@ -60,7 +60,7 @@
         if (mTargetViewRootImpl == null) {
             return;
         }
-        mTargetSc = mTargetViewRootImpl.getRenderSurfaceControl();
+        mTargetSc = mTargetViewRootImpl.getSurfaceControl();
         mTargetViewRootImpl.registerRtFrameCallback(frame -> {
             if (mTargetSc == null || !mTargetSc.isValid()) {
                 return;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e00ff7e..5235740 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -105,6 +105,7 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.FrameInfo;
+import android.graphics.HardwareRenderer;
 import android.graphics.HardwareRenderer.FrameDrawingCallback;
 import android.graphics.Insets;
 import android.graphics.Matrix;
@@ -519,7 +520,6 @@
     @UnsupportedAppUsage
     public final Surface mSurface = new Surface();
     private final SurfaceControl mSurfaceControl = new SurfaceControl();
-    private SurfaceControl mBlastSurfaceControl = new SurfaceControl();
 
     private BLASTBufferQueue mBlastBufferQueue;
 
@@ -702,6 +702,11 @@
 
     private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks;
 
+    /**
+     * Increment this value when the surface has been replaced.
+     */
+    private int mSurfaceSequenceId = 0;
+
     private String mTag = TAG;
 
     public ViewRootImpl(Context context, Display display) {
@@ -1808,7 +1813,7 @@
             mBoundsLayer = new SurfaceControl.Builder(mSurfaceSession)
                     .setContainerLayer()
                     .setName("Bounds for - " + getTitle().toString())
-                    .setParent(getRenderSurfaceControl())
+                    .setParent(getSurfaceControl())
                     .setCallsite("ViewRootImpl.getBoundsLayer")
                     .build();
             setBoundsLayerCrop(mTransaction);
@@ -1818,22 +1823,19 @@
     }
 
     Surface getOrCreateBLASTSurface(int width, int height) {
-        if (mSurfaceControl == null
-                || !mSurfaceControl.isValid()
-                || mBlastSurfaceControl == null
-                || !mBlastSurfaceControl.isValid()) {
+        if (!mSurfaceControl.isValid()) {
             return null;
         }
 
         Surface ret = null;
         if (mBlastBufferQueue == null) {
             mBlastBufferQueue = new BLASTBufferQueue(mTag,
-                mBlastSurfaceControl, width, height, mEnableTripleBuffering);
+                    mSurfaceControl, width, height, mEnableTripleBuffering);
             // We only return the Surface the first time, as otherwise
             // it hasn't changed and there is no need to update.
             ret = mBlastBufferQueue.createSurface();
         } else {
-            mBlastBufferQueue.update(mBlastSurfaceControl, width, height);
+            mBlastBufferQueue.update(mSurfaceControl, width, height);
         }
 
         return ret;
@@ -1855,7 +1857,7 @@
     private boolean updateBoundsLayer(SurfaceControl.Transaction t) {
         if (mBoundsLayer != null) {
             setBoundsLayerCrop(t);
-            t.deferTransactionUntil(mBoundsLayer, getRenderSurfaceControl(),
+            t.deferTransactionUntil(mBoundsLayer, getSurfaceControl(),
                 mSurface.getNextFrameNumber());
             return true;
         }
@@ -1864,7 +1866,7 @@
 
     private void prepareSurfaces(boolean sizeChanged) {
         final SurfaceControl.Transaction t = mTransaction;
-        final SurfaceControl sc = getRenderSurfaceControl();
+        final SurfaceControl sc = getSurfaceControl();
         if (!sc.isValid()) return;
 
         boolean applyTransaction = updateBoundsLayer(t);
@@ -1885,7 +1887,6 @@
         mSurface.release();
         mSurfaceControl.release();
 
-        mBlastSurfaceControl.release();
         // We should probably add an explicit dispose.
         mBlastBufferQueue = null;
     }
@@ -2613,7 +2614,7 @@
         boolean surfaceSizeChanged = false;
         boolean surfaceCreated = false;
         boolean surfaceDestroyed = false;
-        /* True if surface generation id changes. */
+        // True if surface generation id changes or relayout result is RELAYOUT_RES_SURFACE_CHANGED.
         boolean surfaceReplaced = false;
 
         final boolean windowAttributesChanged = mWindowAttributesChanged;
@@ -2708,6 +2709,7 @@
                 updateColorModeIfNeeded(lp.getColorMode());
                 surfaceCreated = !hadSurface && mSurface.isValid();
                 surfaceDestroyed = hadSurface && !mSurface.isValid();
+
                 // When using Blast, the surface generation id may not change when there's a new
                 // SurfaceControl. In that case, we also check relayout flag
                 // RELAYOUT_RES_SURFACE_CHANGED since it should indicate that WMS created a new
@@ -2716,6 +2718,9 @@
                         || (relayoutResult & RELAYOUT_RES_SURFACE_CHANGED)
                         == RELAYOUT_RES_SURFACE_CHANGED)
                         && mSurface.isValid();
+                if (surfaceReplaced) {
+                    mSurfaceSequenceId++;
+                }
 
                 if (cutoutChanged) {
                     mAttachInfo.mDisplayCutout.set(mPendingDisplayCutout);
@@ -3815,6 +3820,82 @@
         }
     }
 
+    /**
+     * The callback will run on the render thread.
+     */
+    private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler,
+            boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) {
+        return frameNr -> {
+            // Use a new transaction here since mRtBLASTSyncTransaction can only be accessed by
+            // the render thread and mSurfaceChangedTransaction can only be accessed by the UI
+            // thread. The temporary transaction is used so mRtBLASTSyncTransaction can be merged
+            // with mSurfaceChangedTransaction without synchronization issues.
+            final Transaction t = new Transaction();
+            finishBLASTSyncOnRT(!mSendNextFrameToWm, t);
+            handler.postAtFrontOfQueue(() -> {
+                mSurfaceChangedTransaction.merge(t);
+                if (reportNextDraw) {
+                    // TODO: Use the frame number
+                    pendingDrawFinished();
+                }
+                if (commitCallbacks != null) {
+                    for (int i = 0; i < commitCallbacks.size(); i++) {
+                        commitCallbacks.get(i).run();
+                    }
+                }
+            });
+        };
+    }
+
+    private boolean addFrameCompleteCallbackIfNeeded() {
+        if (mAttachInfo.mThreadedRenderer == null || !mAttachInfo.mThreadedRenderer.isEnabled()) {
+            return false;
+        }
+
+        ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
+                .captureFrameCommitCallbacks();
+        final boolean needFrameCompleteCallback =
+                mNextDrawUseBLASTSyncTransaction || mReportNextDraw
+                        || (commitCallbacks != null && commitCallbacks.size() > 0);
+        if (needFrameCompleteCallback) {
+            mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(
+                    createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw,
+                            commitCallbacks));
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * The callback will run on a worker thread pool from the render thread.
+     */
+    private HardwareRenderer.FrameDrawingCallback createFrameDrawingCallback() {
+        return frame -> {
+            mRtNextFrameReportedConsumeWithBlast = true;
+            if (mBlastBufferQueue != null) {
+                // We don't need to synchronize mRtBLASTSyncTransaction here since it's not
+                // being modified and only sent to BlastBufferQueue.
+                mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction);
+            }
+        };
+    }
+
+    private void addFrameCallbackIfNeeded() {
+        if (!mNextDrawUseBLASTSyncTransaction) {
+            return;
+        }
+
+        // Frame callbacks will always occur after submitting draw requests and before
+        // the draw actually occurs. This will ensure that we set the next transaction
+        // for the frame that's about to get drawn and not on a previous frame that.
+        //
+        // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be
+        // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the
+        // next frame completed should be reported with the blast sync transaction.
+        registerRtFrameCallback(createFrameDrawingCallback());
+        mNextDrawUseBLASTSyncTransaction = false;
+    }
+
     private void performDraw() {
         if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
             return;
@@ -3828,58 +3909,14 @@
         mIsDrawing = true;
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
 
-        boolean usingAsyncReport = false;
-        boolean reportNextDraw = mReportNextDraw; // Capture the original value
-        if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
-            ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
-                    .captureFrameCommitCallbacks();
-            final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction ||
-                (commitCallbacks != null && commitCallbacks.size() > 0) ||
-                mReportNextDraw;
-            usingAsyncReport = mReportNextDraw;
-            if (needFrameCompleteCallback) {
-                final Handler handler = mAttachInfo.mHandler;
-                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> {
-                        finishBLASTSync(!mSendNextFrameToWm);
-                        handler.postAtFrontOfQueue(() -> {
-                            if (reportNextDraw) {
-                                // TODO: Use the frame number
-                                pendingDrawFinished();
-                            }
-                            if (commitCallbacks != null) {
-                                for (int i = 0; i < commitCallbacks.size(); i++) {
-                                    commitCallbacks.get(i).run();
-                                }
-                            }
-                        });
-                });
-            }
-        }
+        boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded();
+        addFrameCallbackIfNeeded();
 
         try {
-            if (mNextDrawUseBLASTSyncTransaction) {
-                // Frame callbacks will always occur after submitting draw requests and before
-                // the draw actually occurs. This will ensure that we set the next transaction
-                // for the frame that's about to get drawn and not on a previous frame that.
-                //
-                // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be
-                // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the
-                // next frame completed should be reported with the blast sync transaction.
-                registerRtFrameCallback(frame -> {
-                    mRtNextFrameReportedConsumeWithBlast = true;
-                    if (mBlastBufferQueue != null) {
-                        // We don't need to synchronize mRtBLASTSyncTransaction here since it's not
-                        // being modified and only sent to BlastBufferQueue.
-                        mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction);
-                    }
-                });
-                mNextDrawUseBLASTSyncTransaction = false;
-            }
             boolean canUseAsync = draw(fullRedrawNeeded);
             if (usingAsyncReport && !canUseAsync) {
                 mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null);
                 usingAsyncReport = false;
-                finishBLASTSync(true /* apply */);
             }
         } finally {
             mIsDrawing = false;
@@ -7447,7 +7484,7 @@
                 (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
                 insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
                 mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
-                mTempControls, mSurfaceSize, mBlastSurfaceControl);
+                mTempControls, mSurfaceSize);
         mPendingDisplayCutout.set(mTmpFrames.displayCutout);
         mPendingBackDropFrame.set(mTmpFrames.backdropFrame);
         if (mSurfaceControl.isValid()) {
@@ -9844,7 +9881,12 @@
         mNextDrawUseBLASTSyncTransaction = true;
     }
 
-    private void finishBLASTSync(boolean apply) {
+    /**
+     * This should only be called from the render thread.
+     */
+    private void finishBLASTSyncOnRT(boolean apply, Transaction t) {
+        // This is safe to modify on the render thread since the only other place it's modified
+        // is on the UI thread when the render thread is paused.
         mSendNextFrameToWm = false;
         if (mRtNextFrameReportedConsumeWithBlast) {
             mRtNextFrameReportedConsumeWithBlast = false;
@@ -9855,7 +9897,7 @@
             if (apply) {
                 mRtBLASTSyncTransaction.apply();
             } else {
-                mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction);
+                t.merge(mRtBLASTSyncTransaction);
             }
         }
     }
@@ -9868,17 +9910,6 @@
         return mRtBLASTSyncTransaction;
     }
 
-    /**
-     * @hide
-     */
-    public SurfaceControl getRenderSurfaceControl() {
-        if (useBLAST()) {
-            return mBlastSurfaceControl;
-        } else {
-            return mSurfaceControl;
-        }
-    }
-
     @Override
     public void onDescendantUnbufferedRequested() {
         mUnbufferedInputSource = mView.mUnbufferedInputSource;
@@ -9895,4 +9926,8 @@
     boolean useBLAST() {
         return mUseBLASTAdapter && !mForceDisableBLAST;
     }
+
+    int getSurfaceSequenceId() {
+        return mSurfaceSequenceId;
+    }
 }
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index dbd8184..0c221ed 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -227,8 +227,7 @@
             int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
             ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
-            SurfaceControl outBLASTSurfaceControl) {
+            InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
         final State state;
         synchronized (this) {
             state = mStateForWindow.get(window.asBinder());
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index d80d230..f6d6fde 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -199,7 +199,7 @@
  * <b>Window state changed</b> - represents the event of a change to a section of
  * the user interface that is visually distinct. Should be sent from either the
  * root view of a window or from a view that is marked as a pane
- * {@link android.view.View#setAccessibilityPaneTitle(CharSequence)}. Not that changes
+ * {@link android.view.View#setAccessibilityPaneTitle(CharSequence)}. Note that changes
  * to true windows are represented by {@link #TYPE_WINDOWS_CHANGED}.</br>
  * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
  * <em>Properties:</em></br>
diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl
index 12b16ff..3a84c1f 100644
--- a/core/java/android/window/ITaskOrganizerController.aidl
+++ b/core/java/android/window/ITaskOrganizerController.aidl
@@ -17,7 +17,9 @@
 package android.window;
 
 import android.app.ActivityManager;
+import android.content.pm.ParceledListSlice;
 import android.window.ITaskOrganizer;
+import android.window.TaskAppearedInfo;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
@@ -26,8 +28,11 @@
 
     /**
      * Register a TaskOrganizer to manage all the tasks with supported windowing modes.
+     *
+     * @return a list of the tasks that should be managed by the organizer, not including tasks
+     *         created via {@link #createRootTask}.
      */
-    void registerTaskOrganizer(ITaskOrganizer organizer);
+    ParceledListSlice<TaskAppearedInfo> registerTaskOrganizer(ITaskOrganizer organizer);
 
     /**
      * Unregisters a previously registered task organizer.
diff --git a/core/java/android/window/TaskAppearedInfo.aidl b/core/java/android/window/TaskAppearedInfo.aidl
new file mode 100644
index 0000000..13eba25f
--- /dev/null
+++ b/core/java/android/window/TaskAppearedInfo.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2020 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 android.window;
+
+/**
+ * Data object for the task info provided when a task is presented to an organizer.
+ * @hide
+ */
+parcelable TaskAppearedInfo;
+
diff --git a/core/java/android/window/TaskAppearedInfo.java b/core/java/android/window/TaskAppearedInfo.java
new file mode 100644
index 0000000..2ff331e
--- /dev/null
+++ b/core/java/android/window/TaskAppearedInfo.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 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 android.window;
+
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.SurfaceControl;
+
+/**
+ * Data object for the task info provided when a task is presented to an organizer.
+ * @hide
+ */
+@TestApi
+public final class TaskAppearedInfo implements Parcelable {
+
+    @NonNull
+    private final RunningTaskInfo mTaskInfo;
+
+    @NonNull
+    private final SurfaceControl mLeash;
+
+    @NonNull
+    public static final Creator<TaskAppearedInfo> CREATOR = new Creator<TaskAppearedInfo>() {
+        @Override
+        public TaskAppearedInfo createFromParcel(Parcel source) {
+            final RunningTaskInfo taskInfo = source.readTypedObject(RunningTaskInfo.CREATOR);
+            final SurfaceControl leash = source.readTypedObject(SurfaceControl.CREATOR);
+            return new TaskAppearedInfo(taskInfo, leash);
+        }
+
+        @Override
+        public TaskAppearedInfo[] newArray(int size) {
+            return new TaskAppearedInfo[size];
+        }
+
+    };
+
+    public TaskAppearedInfo(@NonNull RunningTaskInfo taskInfo, @NonNull SurfaceControl leash) {
+        mTaskInfo = taskInfo;
+        mLeash = leash;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeTypedObject(mTaskInfo, flags);
+        dest.writeTypedObject(mLeash, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * @return the task info.
+     */
+    @NonNull
+    public RunningTaskInfo getTaskInfo() {
+        return mTaskInfo;
+    }
+
+    /**
+     * @return the leash for the task.
+     */
+    @NonNull
+    public SurfaceControl getLeash() {
+        return mLeash;
+    }
+}
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index a7cb642..909bb47 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -17,6 +17,7 @@
 package android.window;
 
 import android.annotation.BinderThread;
+import android.annotation.CallSuper;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -51,11 +52,16 @@
 
     /**
      * Register a TaskOrganizer to manage tasks as they enter a supported windowing mode.
+     *
+     * @return a list of the tasks that should be managed by the organizer, not including tasks
+     *         created via {@link #createRootTask}.
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-    public final void registerOrganizer() {
+    @CallSuper
+    @NonNull
+    public List<TaskAppearedInfo> registerOrganizer() {
         try {
-            mTaskOrganizerController.registerTaskOrganizer(mInterface);
+            return mTaskOrganizerController.registerTaskOrganizer(mInterface).getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -63,7 +69,8 @@
 
     /** Unregisters a previously registered task organizer. */
     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-    public final void unregisterOrganizer() {
+    @CallSuper
+    public void unregisterOrganizer() {
         try {
             mTaskOrganizerController.unregisterTaskOrganizer(mInterface);
         } catch (RemoteException e) {
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index 491ddba..2b4e09d 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -80,6 +80,8 @@
             "com.android.server.accessibility.MagnificationController";
     public static final ComponentName MAGNIFICATION_COMPONENT_NAME =
             new ComponentName("com.android.server.accessibility", "Magnification");
+    public static final ComponentName REDUCE_BRIGHT_COLORS_COMPONENT_NAME =
+            new ComponentName("com.android.server.accessibility", "ReduceBrightColors");
 
     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -126,6 +128,11 @@
                             Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
                             "1" /* Value to enable */, "0" /* Value to disable */,
                             R.string.color_correction_feature_name));
+            featuresMap.put(REDUCE_BRIGHT_COLORS_COMPONENT_NAME,
+                    new ToggleableFrameworkFeatureInfo(
+                            Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
+                            "1" /* Value to enable */, "0" /* Value to disable */,
+                            R.string.reduce_bright_colors_feature_name));
             sFrameworkShortcutFeaturesMap = Collections.unmodifiableMap(featuresMap);
         }
         return sFrameworkShortcutFeaturesMap;
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
index a7c5f6d..9d06bb9 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
@@ -21,6 +21,7 @@
 import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME;
 import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME;
 import static com.android.internal.accessibility.util.AccessibilityUtils.getAccessibilityServiceFragmentType;
 import static com.android.internal.accessibility.util.ShortcutUtils.isShortcutContained;
 
@@ -112,7 +113,7 @@
             @ShortcutType int shortcutType) {
         final List<AccessibilityTarget> targets = new ArrayList<>();
         targets.addAll(getAccessibilityFilteredTargets(context, shortcutType));
-        targets.addAll(getWhiteListingFeatureTargets(context, shortcutType));
+        targets.addAll(getAllowListingFeatureTargets(context, shortcutType));
 
         return targets;
     }
@@ -196,12 +197,12 @@
         return targets;
     }
 
-    private static List<AccessibilityTarget> getWhiteListingFeatureTargets(Context context,
+    private static List<AccessibilityTarget> getAllowListingFeatureTargets(Context context,
             @ShortcutType int shortcutType) {
         final List<AccessibilityTarget> targets = new ArrayList<>();
 
-        final InvisibleToggleWhiteListingFeatureTarget magnification =
-                new InvisibleToggleWhiteListingFeatureTarget(context,
+        final InvisibleToggleAllowListingFeatureTarget magnification =
+                new InvisibleToggleAllowListingFeatureTarget(context,
                 shortcutType,
                 isShortcutContained(context, shortcutType, MAGNIFICATION_CONTROLLER_NAME),
                 MAGNIFICATION_CONTROLLER_NAME,
@@ -209,8 +210,8 @@
                 context.getDrawable(R.drawable.ic_accessibility_magnification),
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
 
-        final ToggleWhiteListingFeatureTarget daltonizer =
-                new ToggleWhiteListingFeatureTarget(context,
+        final ToggleAllowListingFeatureTarget daltonizer =
+                new ToggleAllowListingFeatureTarget(context,
                 shortcutType,
                 isShortcutContained(context, shortcutType,
                         DALTONIZER_COMPONENT_NAME.flattenToString()),
@@ -219,8 +220,8 @@
                 context.getDrawable(R.drawable.ic_accessibility_color_correction),
                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
 
-        final ToggleWhiteListingFeatureTarget colorInversion =
-                new ToggleWhiteListingFeatureTarget(context,
+        final ToggleAllowListingFeatureTarget colorInversion =
+                new ToggleAllowListingFeatureTarget(context,
                 shortcutType,
                 isShortcutContained(context, shortcutType,
                         COLOR_INVERSION_COMPONENT_NAME.flattenToString()),
@@ -229,9 +230,21 @@
                 context.getDrawable(R.drawable.ic_accessibility_color_inversion),
                 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
 
+        // TODO: Update with shortcut icon
+        final ToggleAllowListingFeatureTarget reduceBrightColors =
+                new ToggleAllowListingFeatureTarget(context,
+                        shortcutType,
+                        isShortcutContained(context, shortcutType,
+                                REDUCE_BRIGHT_COLORS_COMPONENT_NAME.flattenToString()),
+                        REDUCE_BRIGHT_COLORS_COMPONENT_NAME.flattenToString(),
+                        context.getString(R.string.reduce_bright_colors_feature_name),
+                        null,
+                        Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED);
+
         targets.add(magnification);
         targets.add(daltonizer);
         targets.add(colorInversion);
+        targets.add(reduceBrightColors);
 
         return targets;
     }
diff --git a/core/java/com/android/internal/accessibility/dialog/InvisibleToggleWhiteListingFeatureTarget.java b/core/java/com/android/internal/accessibility/dialog/InvisibleToggleAllowListingFeatureTarget.java
similarity index 91%
rename from core/java/com/android/internal/accessibility/dialog/InvisibleToggleWhiteListingFeatureTarget.java
rename to core/java/com/android/internal/accessibility/dialog/InvisibleToggleAllowListingFeatureTarget.java
index acd101b..e78036d 100644
--- a/core/java/com/android/internal/accessibility/dialog/InvisibleToggleWhiteListingFeatureTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/InvisibleToggleAllowListingFeatureTarget.java
@@ -26,9 +26,9 @@
  * Extension for {@link AccessibilityTarget} with {@link AccessibilityFragmentType#INVISIBLE_TOGGLE}
  * type.
  */
-class InvisibleToggleWhiteListingFeatureTarget extends AccessibilityTarget {
+class InvisibleToggleAllowListingFeatureTarget extends AccessibilityTarget {
 
-    InvisibleToggleWhiteListingFeatureTarget(Context context, @ShortcutType int shortcutType,
+    InvisibleToggleAllowListingFeatureTarget(Context context, @ShortcutType int shortcutType,
             boolean isShortcutSwitched, String id, CharSequence label, Drawable icon, String key) {
         super(context, shortcutType, AccessibilityFragmentType.INVISIBLE_TOGGLE,
                 isShortcutSwitched, id, label, icon, key);
diff --git a/core/java/com/android/internal/accessibility/dialog/ToggleWhiteListingFeatureTarget.java b/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java
similarity index 94%
rename from core/java/com/android/internal/accessibility/dialog/ToggleWhiteListingFeatureTarget.java
rename to core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java
index 5ab9eb8..38aac70 100644
--- a/core/java/com/android/internal/accessibility/dialog/ToggleWhiteListingFeatureTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java
@@ -32,9 +32,9 @@
  * Extension for {@link AccessibilityTarget} with {@link AccessibilityFragmentType#TOGGLE}
  * type.
  */
-class ToggleWhiteListingFeatureTarget extends AccessibilityTarget {
+class ToggleAllowListingFeatureTarget extends AccessibilityTarget {
 
-    ToggleWhiteListingFeatureTarget(Context context, @ShortcutType int shortcutType,
+    ToggleAllowListingFeatureTarget(Context context, @ShortcutType int shortcutType,
             boolean isShortcutSwitched, String id, CharSequence label, Drawable icon, String key) {
         super(context, shortcutType, AccessibilityFragmentType.TOGGLE,
                 isShortcutSwitched, id, label, icon, key);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 17323ba..4c5f988 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -65,7 +65,6 @@
 import android.telephony.CellSignalStrength;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
-import android.telephony.ModemActivityInfo.TransmitPower;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
@@ -7791,7 +7790,7 @@
         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
             if (mModemControllerActivity == null) {
                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
-                        ModemActivityInfo.TX_POWER_LEVELS);
+                        ModemActivityInfo.getNumTxPowerLevels());
             }
             return mModemControllerActivity;
         }
@@ -9257,7 +9256,7 @@
 
             if (in.readInt() != 0) {
                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
-                        ModemActivityInfo.TX_POWER_LEVELS, in);
+                        ModemActivityInfo.getNumTxPowerLevels(), in);
             } else {
                 mModemControllerActivity = null;
             }
@@ -10520,7 +10519,7 @@
         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
                 NUM_BT_TX_LEVELS);
         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
-                ModemActivityInfo.TX_POWER_LEVELS);
+                ModemActivityInfo.getNumTxPowerLevels());
         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
                 mOnBatteryTimeBase);
@@ -11710,26 +11709,7 @@
         }
     }
 
-    private ModemActivityInfo mLastModemActivityInfo =
-            new ModemActivityInfo(0, 0, 0, new int[0], 0);
-
-    private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
-        if (activityInfo == null) {
-            return null;
-        }
-        int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
-        for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
-            txTimeMs[i] = activityInfo.getTransmitPowerInfo().get(i).getTimeInMillis()
-                    - mLastModemActivityInfo.getTransmitPowerInfo().get(i).getTimeInMillis();
-        }
-        ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
-                activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
-                activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
-                txTimeMs,
-                activityInfo.getReceiveTimeMillis() - mLastModemActivityInfo.getReceiveTimeMillis());
-        mLastModemActivityInfo = activityInfo;
-        return deltaInfo;
-    }
+    private ModemActivityInfo mLastModemActivityInfo = null;
 
     /**
      * Distribute Cell radio energy info and network traffic to apps.
@@ -11746,7 +11726,9 @@
         if (DEBUG_ENERGY) {
             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
         }
-        ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
+        ModemActivityInfo deltaInfo = mLastModemActivityInfo == null ? activityInfo
+                : mLastModemActivityInfo.getDelta(activityInfo);
+        mLastModemActivityInfo = activityInfo;
 
         // Add modem tx power to history.
         addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs);
@@ -11778,10 +11760,9 @@
                 mModemActivity.getSleepTimeCounter().addCountLocked(
                         deltaInfo.getSleepTimeMillis());
                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getReceiveTimeMillis());
-                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
+                for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels(); lvl++) {
                     mModemActivity.getTxTimeCounters()[lvl]
-                        .addCountLocked(deltaInfo.getTransmitPowerInfo()
-                            .get(lvl).getTimeInMillis());
+                        .addCountLocked(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl));
                 }
 
                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
@@ -11795,11 +11776,11 @@
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
                             + deltaInfo.getReceiveTimeMillis() *
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
-                    List<TransmitPower> txPowerInfo = deltaInfo.getTransmitPowerInfo();
-                    for (int i = 0; i < Math.min(txPowerInfo.size(),
+                    for (int i = 0; i < Math.min(ModemActivityInfo.getNumTxPowerLevels(),
                             CellSignalStrength.getNumSignalStrengthLevels()); i++) {
-                        energyUsed += txPowerInfo.get(i).getTimeInMillis() * mPowerProfile
-                            .getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
+                        energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i)
+                                * mPowerProfile.getAveragePower(
+                                        PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
                     }
 
                     // We store the power drain as mAms.
@@ -11894,10 +11875,10 @@
                             }
 
                             if (totalTxPackets > 0 && entry.txPackets > 0) {
-                                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
-                                    long txMs =
-                                            entry.txPackets * deltaInfo.getTransmitPowerInfo()
-                                                .get(lvl).getTimeInMillis();
+                                for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels();
+                                        lvl++) {
+                                    long txMs = entry.txPackets
+                                            * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
                                     txMs /= totalTxPackets;
                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
                                 }
@@ -11929,18 +11910,14 @@
         if (activityInfo == null) {
             return;
         }
-        List<TransmitPower> txPowerInfo = activityInfo.getTransmitPowerInfo();
-        if (txPowerInfo == null || txPowerInfo.size() != ModemActivityInfo.TX_POWER_LEVELS) {
-            return;
-        }
         int levelMaxTimeSpent = 0;
-        for (int i = 1; i < txPowerInfo.size(); i++) {
-            if (txPowerInfo.get(i).getTimeInMillis() > txPowerInfo.get(levelMaxTimeSpent)
-                .getTimeInMillis()) {
+        for (int i = 1; i < ModemActivityInfo.getNumTxPowerLevels(); i++) {
+            if (activityInfo.getTransmitDurationMillisAtPowerLevel(i)
+                    > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) {
                 levelMaxTimeSpent = i;
             }
         }
-        if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
+        if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) {
             mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
             addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
         }
@@ -13462,7 +13439,7 @@
             timeInRxSignalStrengthLevelMs[i] =
                 getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000;
         }
-        long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
+        long[] txTimeMs = new long[Math.min(ModemActivityInfo.getNumTxPowerLevels(),
             counter.getTxTimeCounters().length)];
         long totalTxTimeMs = 0;
         for (int i = 0; i < txTimeMs.length; i++) {
@@ -15601,7 +15578,7 @@
         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
                 NUM_BT_TX_LEVELS, in);
         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
-                ModemActivityInfo.TX_POWER_LEVELS, in);
+                ModemActivityInfo.getNumTxPowerLevels(), in);
         mHasWifiReporting = in.readInt() != 0;
         mHasBluetoothReporting = in.readInt() != 0;
         mHasModemReporting = in.readInt() != 0;
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index caae518..77c7ce8 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -102,6 +102,13 @@
     void onCameraLaunchGestureDetected(int source);
 
     /**
+     * Notifies the status bar that the Emergency Action launch gesture has been detected.
+     *
+     * TODO(b/169175022) Update method name and docs when feature name is locked.
+     */
+    void onEmergencyActionLaunchGestureDetected();
+
+    /**
      * Shows the picture-in-picture menu if an activity is in picture-in-picture mode.
      */
     void showPictureInPictureMenu();
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 9ed71ac0..1ea918a 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -343,7 +343,7 @@
                                     jboolean(focusEvent->getHasFocus()),
                                     jboolean(focusEvent->getInTouchMode()));
                 finishInputEvent(seq, true /* handled */);
-                return OK;
+                continue;
             }
 
             default:
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 32ce5e2..99fe1af 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2756,4 +2756,9 @@
     // CATEGORY: SETTINGS
     // OS: S
     SCREEN_TIMEOUT = 1852;
+
+    // OPEN: Settings > Accessibility > Reduce Bright Colors
+    // CATEGORY: SETTINGS
+    // OS: S
+    REDUCE_BRIGHT_COLORS_SETTINGS = 1853;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e2f4f2f..f2af514 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4518,6 +4518,12 @@
     <permission android:name="android.permission.MANAGE_NOTIFICATIONS"
                 android:protectionLevel="signature" />
 
+    <!-- @SystemApi @TestApi Allows adding/removing enabled notification listener components.
+        @hide -->
+    <permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS"
+                android:protectionLevel="signature" />
+    <uses-permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS" />
+
     <!-- Allows notifications to be colorized
          <p>Not for use by third-party applications. @hide -->
     <permission android:name="android.permission.USE_COLORIZED_NOTIFICATIONS"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fc489b1..645bae7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4494,6 +4494,9 @@
      shown in the warning dialog about the accessibility shortcut. -->
     <string name="color_correction_feature_name">Color Correction</string>
 
+    <!-- Title of Reduce Bright Colors feature, shown in the warning dialog about the accessibility shortcut. [CHAR LIMIT=none] -->
+    <string name="reduce_bright_colors_feature_name">Reduce Bright Colors</string>
+
     <!-- Text in toast to alert the user that the accessibility shortcut turned on an accessibility service. [CHAR LIMIT=none] -->
     <string name="accessibility_shortcut_enabling_service">Held volume keys. <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g> turned on.</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1249b17..9b52f54 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3249,6 +3249,7 @@
   <java-symbol type="string" name="accessibility_shortcut_disabling_service" />
   <java-symbol type="string" name="color_inversion_feature_name" />
   <java-symbol type="string" name="color_correction_feature_name" />
+  <java-symbol type="string" name="reduce_bright_colors_feature_name" />
   <java-symbol type="string" name="config_defaultAccessibilityService" />
   <java-symbol type="string" name="accessibility_shortcut_spoken_feedback" />
 
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index e122e00..745de84 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -149,3 +149,11 @@
     src: "com.android.car.ui.paintbooth.xml",
     filename_from_src: true,
 }
+
+prebuilt_etc {
+    name: "allowed_privapp_com.android.car.provision",
+    system_ext_specific: true,
+    sub_dir: "permissions",
+    src: "com.android.car.provision.xml",
+    filename_from_src: true,
+}
\ No newline at end of file
diff --git a/data/etc/car/com.android.car.provision.xml b/data/etc/car/com.android.car.provision.xml
new file mode 100644
index 0000000..fa51d55e
--- /dev/null
+++ b/data/etc/car/com.android.car.provision.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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
+  -->
+<permissions>
+    <privapp-permissions package="com.android.car.provision">
+        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+        <permission name="android.permission.WRITE_SETTINGS"/>
+    </privapp-permissions>
+</permissions>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 28d7911..a191fe5 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -115,6 +115,21 @@
         Align.LEFT, Align.CENTER, Align.RIGHT
     };
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, value = {
+            ANTI_ALIAS_FLAG,
+            FILTER_BITMAP_FLAG,
+            DITHER_FLAG,
+            UNDERLINE_TEXT_FLAG,
+            STRIKE_THRU_TEXT_FLAG,
+            FAKE_BOLD_TEXT_FLAG,
+            LINEAR_TEXT_FLAG,
+            SUBPIXEL_TEXT_FLAG,
+            EMBEDDED_BITMAP_TEXT_FLAG
+    })
+    public @interface PaintFlag{}
+
     /**
      * Paint flag that enables antialiasing when drawing.
      *
@@ -724,7 +739,7 @@
      *
      * @return the paint's flags (see enums ending in _Flag for bit masks)
      */
-    public int getFlags() {
+    public @PaintFlag int getFlags() {
         return nGetFlags(mNativePaint);
     }
 
@@ -733,7 +748,7 @@
      *
      * @param flags The new flag bits for the paint
      */
-    public void setFlags(int flags) {
+    public void setFlags(@PaintFlag int flags) {
         nSetFlags(mNativePaint, flags);
     }
 
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index bcef154..44744bc 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -7,6 +7,12 @@
       "group": "WM_SHELL_TASK_ORG",
       "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
     },
+    "-1683614271": {
+      "message": "Existing task: id=%d component=%s",
+      "level": "VERBOSE",
+      "group": "WM_SHELL_TASK_ORG",
+      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
+    },
     "-1534364071": {
       "message": "onTransitionReady %s: %s",
       "level": "VERBOSE",
@@ -61,6 +67,12 @@
       "group": "WM_SHELL_TASK_ORG",
       "at": "com\/android\/wm\/shell\/FullscreenTaskListener.java"
     },
+    "580605218": {
+      "message": "Registering organizer",
+      "level": "VERBOSE",
+      "group": "WM_SHELL_TASK_ORG",
+      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
+    },
     "980952660": {
       "message": "Task root back pressed taskId=%d",
       "level": "VERBOSE",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 7ce65fd..d87de5a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -28,12 +28,14 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.WindowConfiguration.WindowingMode;
 import android.util.Log;
-import android.util.Pair;
 import android.util.SparseArray;
 import android.view.SurfaceControl;
 import android.window.ITaskOrganizerController;
+import android.window.TaskAppearedInfo;
 import android.window.TaskOrganizer;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.ShellExecutor;
@@ -42,6 +44,7 @@
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * Unified task organizer for all components in the shell.
@@ -82,7 +85,7 @@
 
     // Keeps track of all the tasks reported to this organizer (changes in windowing mode will
     // require us to report to both old and new listeners)
-    private final SparseArray<Pair<RunningTaskInfo, SurfaceControl>> mTasks = new SparseArray<>();
+    private final SparseArray<TaskAppearedInfo> mTasks = new SparseArray<>();
 
     // TODO(shell-transitions): move to a more "global" Shell location as this isn't only for Tasks
     private final Transitions mTransitions;
@@ -102,6 +105,19 @@
         if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
     }
 
+    @Override
+    public List<TaskAppearedInfo> registerOrganizer() {
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Registering organizer");
+        final List<TaskAppearedInfo> taskInfos = super.registerOrganizer();
+        for (int i = 0; i < taskInfos.size(); i++) {
+            final TaskAppearedInfo info = taskInfos.get(i);
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Existing task: id=%d component=%s",
+                    info.getTaskInfo().taskId, info.getTaskInfo().baseIntent);
+            onTaskAppeared(info.getTaskInfo(), info.getLeash());
+        }
+        return taskInfos;
+    }
+
     /**
      * Adds a listener for tasks with given types.
      */
@@ -117,10 +133,11 @@
 
             // Notify the listener of all existing tasks with the given type.
             for (int i = mTasks.size() - 1; i >= 0; i--) {
-                Pair<RunningTaskInfo, SurfaceControl> data = mTasks.valueAt(i);
-                final @TaskListenerType int taskListenerType = getTaskListenerType(data.first);
+                TaskAppearedInfo data = mTasks.valueAt(i);
+                final @TaskListenerType int taskListenerType = getTaskListenerType(
+                        data.getTaskInfo());
                 if (taskListenerType == listenerType) {
-                    listener.onTaskAppeared(data.first, data.second);
+                    listener.onTaskAppeared(data.getTaskInfo(), data.getLeash());
                 }
             }
         }
@@ -143,7 +160,7 @@
     public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task appeared taskId=%d",
                 taskInfo.taskId);
-        mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, leash));
+        mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, leash));
         final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo));
         if (listener != null) {
             listener.onTaskAppeared(taskInfo, leash);
@@ -154,10 +171,10 @@
     public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task info changed taskId=%d",
                 taskInfo.taskId);
-        final Pair<RunningTaskInfo, SurfaceControl> data = mTasks.get(taskInfo.taskId);
+        final TaskAppearedInfo data = mTasks.get(taskInfo.taskId);
         final @TaskListenerType int listenerType = getTaskListenerType(taskInfo);
-        final @TaskListenerType int prevListenerType = getTaskListenerType(data.first);
-        mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, data.second));
+        final @TaskListenerType int prevListenerType = getTaskListenerType(data.getTaskInfo());
+        mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, data.getLeash()));
         if (prevListenerType != listenerType) {
             // TODO: We currently send vanished/appeared as the task moves between types, but
             //       we should consider adding a different mode-changed callback
@@ -167,7 +184,7 @@
             }
             listener = mTaskListenersByType.get(listenerType);
             if (listener != null) {
-                SurfaceControl leash = data.second;
+                SurfaceControl leash = data.getLeash();
                 listener.onTaskAppeared(taskInfo, leash);
             }
         } else {
@@ -193,7 +210,7 @@
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task vanished taskId=%d",
                 taskInfo.taskId);
         final @TaskListenerType int prevListenerType =
-                getTaskListenerType(mTasks.get(taskInfo.taskId).first);
+                getTaskListenerType(mTasks.get(taskInfo.taskId).getTaskInfo());
         mTasks.remove(taskInfo.taskId);
         final TaskListener listener = mTaskListenersByType.get(prevListenerType);
         if (listener != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 84b98f9..17fd16b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -276,12 +276,11 @@
                 long frameNumber, ClientWindowFrames outFrames,
                 MergedConfiguration mergedConfiguration,
                 SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-                InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
-                SurfaceControl outBLASTSurfaceControl) {
+                InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
             int res = super.relayout(window, attrs, requestedWidth, requestedHeight,
                     viewVisibility, flags, frameNumber, outFrames,
                     mergedConfiguration, outSurfaceControl, outInsetsState,
-                    outActiveControls, outSurfaceSize, outBLASTSurfaceControl);
+                    outActiveControls, outSurfaceSize);
             if (res != 0) {
                 return res;
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
index a0ce9da..f3dadfc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
@@ -26,7 +26,7 @@
 public enum ShellProtoLogGroup implements IProtoLogGroup {
     // NOTE: Since we enable these from the same WM ShellCommand, these names should not conflict
     // with those in the framework ProtoLogGroup
-    WM_SHELL_TASK_ORG(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
+    WM_SHELL_TASK_ORG(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
             Consts.TAG_WM_SHELL),
     WM_SHELL_TRANSITIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
             Consts.TAG_WM_SHELL),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index f01fc51..5418a5b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -22,6 +22,10 @@
 import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW;
 import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
@@ -29,10 +33,12 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager.RunningTaskInfo;
+import android.content.pm.ParceledListSlice;
 import android.os.RemoteException;
 import android.view.SurfaceControl;
 import android.window.ITaskOrganizer;
 import android.window.ITaskOrganizerController;
+import android.window.TaskAppearedInfo;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
@@ -93,8 +99,12 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mOrganizer = new ShellTaskOrganizer(mTaskOrganizerController, mSyncTransactionQueue,
-                mTransactionPool, mTestExecutor, mTestExecutor);
+        try {
+            doReturn(ParceledListSlice.<TaskAppearedInfo>emptyList())
+                    .when(mTaskOrganizerController).registerTaskOrganizer(any());
+        } catch (RemoteException e) {}
+        mOrganizer = spy(new ShellTaskOrganizer(mTaskOrganizerController, mSyncTransactionQueue,
+                mTransactionPool, mTestExecutor, mTestExecutor));
     }
 
     @Test
@@ -116,8 +126,29 @@
     }
 
     @Test
+    public void testRegisterWithExistingTasks() throws RemoteException {
+        // Setup some tasks
+        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+        RunningTaskInfo task2 = createTaskInfo(2, WINDOWING_MODE_MULTI_WINDOW);
+        ArrayList<TaskAppearedInfo> taskInfos = new ArrayList<>();
+        taskInfos.add(new TaskAppearedInfo(task1, new SurfaceControl()));
+        taskInfos.add(new TaskAppearedInfo(task2, new SurfaceControl()));
+        doReturn(new ParceledListSlice(taskInfos))
+                .when(mTaskOrganizerController).registerTaskOrganizer(any());
+
+        // Register and expect the tasks to be stored
+        mOrganizer.registerOrganizer();
+
+        // Check that the tasks are next reported when the listener is added
+        TrackingTaskListener listener = new TrackingTaskListener();
+        mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+        assertTrue(listener.appeared.contains(task1));
+        assertTrue(listener.appeared.contains(task2));
+    }
+
+    @Test
     public void testAppearedVanished() {
-        RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW);
+        RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
         TrackingTaskListener listener = new TrackingTaskListener();
         mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
         mOrganizer.onTaskAppeared(taskInfo, null);
@@ -129,7 +160,7 @@
 
     @Test
     public void testAddListenerExistingTasks() {
-        RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW);
+        RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
         mOrganizer.onTaskAppeared(taskInfo, null);
 
         TrackingTaskListener listener = new TrackingTaskListener();
@@ -139,7 +170,7 @@
 
     @Test
     public void testWindowingModeChange() {
-        RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW);
+        RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
         TrackingTaskListener mwListener = new TrackingTaskListener();
         TrackingTaskListener pipListener = new TrackingTaskListener();
         mOrganizer.addListener(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
@@ -148,14 +179,15 @@
         assertTrue(mwListener.appeared.contains(taskInfo));
         assertTrue(pipListener.appeared.isEmpty());
 
-        taskInfo = createTaskInfo(WINDOWING_MODE_PINNED);
+        taskInfo = createTaskInfo(1, WINDOWING_MODE_PINNED);
         mOrganizer.onTaskInfoChanged(taskInfo);
         assertTrue(mwListener.vanished.contains(taskInfo));
         assertTrue(pipListener.appeared.contains(taskInfo));
     }
 
-    private RunningTaskInfo createTaskInfo(int windowingMode) {
+    private RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
         RunningTaskInfo taskInfo = new RunningTaskInfo();
+        taskInfo.taskId = taskId;
         taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
         return taskInfo;
     }
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index e03643c..4977c21 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -21,6 +21,7 @@
 
 import android.Manifest;
 import android.annotation.FloatRange;
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -38,6 +39,8 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 
@@ -65,16 +68,41 @@
      */
     public static final long PASSIVE_INTERVAL = Long.MAX_VALUE;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({QUALITY_LOW_POWER, QUALITY_BALANCED_POWER_ACCURACY, QUALITY_HIGH_ACCURACY})
+    public @interface Quality {}
+
+    /**
+     * A quality constant indicating a location provider may choose to satisfy this request by
+     * providing very accurate locations at the expense of potentially increased power usage.
+     */
+    public static final int QUALITY_HIGH_ACCURACY = 100;
+
+    /**
+     * A quality constant indicating a location provider may choose to satisfy this request by
+     * equally balancing power and accuracy constraints.
+     */
+    public static final int QUALITY_BALANCED_POWER_ACCURACY = 102;
+
+    /**
+     * A quality constant indicating a location provider may choose to satisfy this request by
+     * providing less accurate locations in order to save power.
+     */
+    public static final int QUALITY_LOW_POWER = 104;
+
     /**
      * Used with {@link #setQuality} to request the most accurate locations available.
      *
      * <p>This may be up to 1 meter accuracy, although this is implementation dependent.
      *
      * @hide
+     * @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead.
      */
+    @Deprecated
     @SystemApi
     @TestApi
-    public static final int ACCURACY_FINE = 100;
+    public static final int ACCURACY_FINE = QUALITY_HIGH_ACCURACY;
 
     /**
      * Used with {@link #setQuality} to request "block" level accuracy.
@@ -84,10 +112,12 @@
      * such as this often consumes less power.
      *
      * @hide
+     * @deprecated Use {@link #QUALITY_BALANCED_POWER_ACCURACY} instead.
      */
+    @Deprecated
     @SystemApi
     @TestApi
-    public static final int ACCURACY_BLOCK = 102;
+    public static final int ACCURACY_BLOCK = QUALITY_BALANCED_POWER_ACCURACY;
 
     /**
      * Used with {@link #setQuality} to request "city" level accuracy.
@@ -97,10 +127,12 @@
      * such as this often consumes less power.
      *
      * @hide
+     * @deprecated Use {@link #QUALITY_LOW_POWER} instead.
      */
+    @Deprecated
     @SystemApi
     @TestApi
-    public static final int ACCURACY_CITY = 104;
+    public static final int ACCURACY_CITY = QUALITY_LOW_POWER;
 
     /**
      * Used with {@link #setQuality} to require no direct power impact (passive locations).
@@ -123,7 +155,9 @@
      * possible.
      *
      * @hide
+     * @deprecated Use {@link #QUALITY_LOW_POWER} instead.
      */
+    @Deprecated
     @SystemApi
     @TestApi
     public static final int POWER_LOW = 201;
@@ -134,7 +168,9 @@
      * <p>This location request will allow high power location work.
      *
      * @hide
+     * @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead.
      */
+    @Deprecated
     @SystemApi
     @TestApi
     public static final int POWER_HIGH = 203;
@@ -144,7 +180,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link "
             + "LocationManager} methods to provide the provider explicitly.")
     @Nullable private String mProvider;
-    private int mQuality;
+    private @Quality int mQuality;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link "
             + "LocationRequest} instead.")
     private long mInterval;
@@ -168,7 +204,7 @@
     public static LocationRequest create() {
         // 60 minutes is the default legacy interval
         return new LocationRequest.Builder(60 * 60 * 1000)
-                .setQuality(POWER_LOW)
+                .setQuality(QUALITY_LOW_POWER)
                 .build();
     }
 
@@ -241,7 +277,7 @@
     private LocationRequest(
             @Nullable String provider,
             long intervalMillis,
-            int quality,
+            @Quality int quality,
             long expireAtRealtimeMillis,
             long durationMillis,
             int maxUpdates,
@@ -251,9 +287,6 @@
             boolean locationSettingsIgnored,
             boolean lowPower,
             WorkSource workSource) {
-        Preconditions.checkArgument(intervalMillis != PASSIVE_INTERVAL || quality == POWER_NONE);
-        Preconditions.checkArgument(minUpdateIntervalMillis <= intervalMillis);
-
         mProvider = provider;
         mInterval = intervalMillis;
         mQuality = quality;
@@ -297,24 +330,39 @@
     @SystemApi
     @Deprecated
     public @NonNull LocationRequest setQuality(int quality) {
-        mQuality = Builder.checkQuality(quality, true);
+        switch (quality) {
+            case POWER_HIGH:
+                // fall through
+            case ACCURACY_FINE:
+                mQuality = QUALITY_HIGH_ACCURACY;
+                break;
+            case ACCURACY_BLOCK:
+                mQuality = QUALITY_BALANCED_POWER_ACCURACY;
+                break;
+            case POWER_LOW:
+                // fall through
+            case ACCURACY_CITY:
+                mQuality = QUALITY_LOW_POWER;
+                break;
+            case POWER_NONE:
+                mInterval = PASSIVE_INTERVAL;
+                break;
+            default:
+                throw new IllegalArgumentException("invalid quality: " + quality);
+        }
+
         return this;
     }
 
     /**
-     * Returns the quality of the location request.
+     * Returns the quality hint for this location request. The quality hint informs the provider how
+     * it should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this
+     * location request.
      *
-     * @return the quality of the location request
-     *
-     * @hide
+     * @return the desired quality tradeoffs between accuracy and power
      */
-    @SystemApi
-    public int getQuality() {
-        if (mInterval == PASSIVE_INTERVAL) {
-            return POWER_NONE;
-        } else {
-            return mQuality;
-        }
+    public @Quality int getQuality() {
+        return mQuality;
     }
 
     /**
@@ -749,97 +797,65 @@
         if (mProvider != null) {
             s.append(mProvider).append(" ");
         }
-        if (mQuality != POWER_NONE && mQuality != ACCURACY_BLOCK) {
-            s.append(qualityToString(mQuality)).append(" ");
-        }
         if (mInterval != PASSIVE_INTERVAL) {
             s.append("@");
             TimeUtils.formatDuration(mInterval, s);
+
+            switch (mQuality) {
+                case QUALITY_HIGH_ACCURACY:
+                    s.append(" HIGH_ACCURACY");
+                    break;
+                case QUALITY_BALANCED_POWER_ACCURACY:
+                    s.append(" BALANCED");
+                    break;
+                case QUALITY_LOW_POWER:
+                    s.append(" LOW_POWER");
+                    break;
+            }
         } else {
             s.append("PASSIVE");
         }
         if (mExpireAtRealtimeMillis != Long.MAX_VALUE) {
-            s.append(" expireAt=").append(TimeUtils.formatRealtime(mExpireAtRealtimeMillis));
+            s.append(", expireAt=").append(TimeUtils.formatRealtime(mExpireAtRealtimeMillis));
         }
         if (mDurationMillis != Long.MAX_VALUE) {
-            s.append(" duration=");
+            s.append(", duration=");
             TimeUtils.formatDuration(mDurationMillis, s);
         }
         if (mMaxUpdates != Integer.MAX_VALUE) {
-            s.append(" maxUpdates=").append(mMaxUpdates);
+            s.append(", maxUpdates=").append(mMaxUpdates);
         }
         if (mMinUpdateIntervalMillis != IMPLICIT_MIN_UPDATE_INTERVAL
                 && mMinUpdateIntervalMillis < mInterval) {
-            s.append(" minUpdateInterval=");
+            s.append(", minUpdateInterval=");
             TimeUtils.formatDuration(mMinUpdateIntervalMillis, s);
         }
         if (mMinUpdateDistanceMeters > 0.0) {
-            s.append(" minUpdateDistance=").append(mMinUpdateDistanceMeters);
+            s.append(", minUpdateDistance=").append(mMinUpdateDistanceMeters);
         }
         if (mLowPower) {
-            s.append(" lowPower");
+            s.append(", lowPower");
         }
         if (mHideFromAppOps) {
-            s.append(" hiddenFromAppOps");
+            s.append(", hiddenFromAppOps");
         }
         if (mLocationSettingsIgnored) {
-            s.append(" locationSettingsIgnored");
+            s.append(", locationSettingsIgnored");
         }
-        if (mWorkSource != null) {
-            s.append(" ").append(mWorkSource);
+        if (mWorkSource != null && !mWorkSource.isEmpty()) {
+            s.append(", ").append(mWorkSource);
         }
         s.append(']');
         return s.toString();
     }
 
-    private static String qualityToString(int quality) {
-        switch (quality) {
-            case ACCURACY_FINE:
-                return "ACCURACY_FINE";
-            case ACCURACY_BLOCK:
-                return "ACCURACY_BLOCK";
-            case ACCURACY_CITY:
-                return "ACCURACY_CITY";
-            case POWER_NONE:
-                return "POWER_NONE";
-            case POWER_LOW:
-                return "POWER_LOW";
-            case POWER_HIGH:
-                return "POWER_HIGH";
-            default:
-                return "???";
-        }
-    }
-
     /**
      * A builder class for {@link LocationRequest}.
      */
     public static final class Builder {
 
-        private static int checkQuality(int quality, boolean allowDeprecated) {
-            switch (quality) {
-                case ACCURACY_FINE:
-                    // fall through
-                case ACCURACY_BLOCK:
-                    // fall through
-                case ACCURACY_CITY:
-                    // fall through
-                case POWER_LOW:
-                    // fall through
-                case POWER_HIGH:
-                    return quality;
-                case POWER_NONE:
-                    if (allowDeprecated) {
-                        return quality;
-                    }
-                    // fall through
-                default:
-                    throw new IllegalArgumentException("invalid quality: " + quality);
-            }
-        }
-
         private long mIntervalMillis;
-        private int mQuality;
+        private @Quality int mQuality;
         private long mDurationMillis;
         private int mMaxUpdates;
         private long mMinUpdateIntervalMillis;
@@ -857,7 +873,7 @@
             // gives us a range check
             setIntervalMillis(intervalMillis);
 
-            mQuality = ACCURACY_BLOCK;
+            mQuality = QUALITY_BALANCED_POWER_ACCURACY;
             mDurationMillis = Long.MAX_VALUE;
             mMaxUpdates = Integer.MAX_VALUE;
             mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL;
@@ -885,9 +901,6 @@
 
             // handle edge cases that can only happen with location request that has been modified
             // by deprecated SystemApi methods
-            if (mQuality == POWER_NONE) {
-                mIntervalMillis = PASSIVE_INTERVAL;
-            }
             if (mIntervalMillis == PASSIVE_INTERVAL
                     && mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) {
                 // this is the legacy default minimum update interval, so if we're forced to
@@ -914,11 +927,17 @@
         }
 
         /**
-         * @hide
+         * Sets the request quality. The quality is a hint to providers on how they should weigh
+         * power vs accuracy tradeoffs. High accuracy locations may cost more power to produce, and
+         * lower accuracy locations may cost less power to produce. Defaults to
+         * {@link #QUALITY_BALANCED_POWER_ACCURACY}.
          */
-        @SystemApi
-        public @NonNull Builder setQuality(int quality) {
-            mQuality = checkQuality(quality, false);
+        public @NonNull Builder setQuality(@Quality int quality) {
+            Preconditions.checkArgument(
+                    quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY
+                            || quality == QUALITY_HIGH_ACCURACY,
+                    "quality must be a defined QUALITY constant, not " + quality);
+            mQuality = quality;
             return this;
         }
 
@@ -1102,7 +1121,7 @@
             return new LocationRequest(
                     null,
                     mIntervalMillis,
-                    mIntervalMillis != PASSIVE_INTERVAL ? mQuality : POWER_NONE,
+                    mQuality,
                     Long.MAX_VALUE,
                     mDurationMillis,
                     mMaxUpdates,
diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java
index fee86ce..00ba552 100644
--- a/location/java/com/android/internal/location/ProviderRequest.java
+++ b/location/java/com/android/internal/location/ProviderRequest.java
@@ -16,10 +16,15 @@
 
 package com.android.internal.location;
 
+import static android.location.LocationRequest.QUALITY_BALANCED_POWER_ACCURACY;
+import static android.location.LocationRequest.QUALITY_HIGH_ACCURACY;
+import static android.location.LocationRequest.QUALITY_LOW_POWER;
+
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.location.LocationRequest;
+import android.location.LocationRequest.Quality;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -41,7 +46,7 @@
     public static final long INTERVAL_DISABLED = Long.MAX_VALUE;
 
     public static final ProviderRequest EMPTY_REQUEST = new ProviderRequest(
-            INTERVAL_DISABLED, false, false, Collections.emptyList(), new WorkSource());
+            INTERVAL_DISABLED, QUALITY_BALANCED_POWER_ACCURACY, false, false, new WorkSource());
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link "
             + "ProviderRequest}")
@@ -49,6 +54,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link "
             + "ProviderRequest}")
     public final long interval;
+    private final @Quality int mQuality;
     private final boolean mLowPower;
     private final boolean mLocationSettingsIgnored;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link "
@@ -56,15 +62,24 @@
     public final List<LocationRequest> locationRequests;
     private final WorkSource mWorkSource;
 
-    private ProviderRequest(long intervalMillis, boolean lowPower,
-            boolean locationSettingsIgnored, @NonNull List<LocationRequest> locationRequests,
-            @NonNull WorkSource workSource) {
+    private ProviderRequest(long intervalMillis, @Quality int quality, boolean lowPower,
+            boolean locationSettingsIgnored, @NonNull WorkSource workSource) {
         reportLocation = intervalMillis != INTERVAL_DISABLED;
         interval = intervalMillis;
+        mQuality = quality;
         mLowPower = lowPower;
         mLocationSettingsIgnored = locationSettingsIgnored;
-        this.locationRequests = locationRequests;
-        mWorkSource = workSource;
+        if (intervalMillis != INTERVAL_DISABLED) {
+            locationRequests = Collections.singletonList(new LocationRequest.Builder(intervalMillis)
+                    .setQuality(quality)
+                    .setLowPower(lowPower)
+                    .setLocationSettingsIgnored(locationSettingsIgnored)
+                    .setWorkSource(workSource)
+                    .build());
+        } else {
+            locationRequests = Collections.emptyList();
+        }
+        mWorkSource = Objects.requireNonNull(workSource);
     }
 
     /**
@@ -84,6 +99,15 @@
     }
 
     /**
+     * The quality hint for this location request. The quality hint informs the provider how it
+     * should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this
+     * provider request.
+     */
+    public @Quality int getQuality() {
+        return mQuality;
+    }
+
+    /**
      * Whether any applicable hardware low power modes should be used to satisfy this request.
      */
     public boolean isLowPower() {
@@ -100,13 +124,6 @@
     }
 
     /**
-     * The full list of location requests contributing to this provider request.
-     */
-    public @NonNull List<LocationRequest> getLocationRequests() {
-        return locationRequests;
-    }
-
-    /**
      * The power blame for this provider request.
      */
     public @NonNull WorkSource getWorkSource() {
@@ -117,13 +134,17 @@
             new Parcelable.Creator<ProviderRequest>() {
                 @Override
                 public ProviderRequest createFromParcel(Parcel in) {
-                    return new ProviderRequest(
-                            /* intervalMillis= */ in.readLong(),
-                            /* lowPower= */ in.readBoolean(),
-                            /* locationSettingsIgnored= */ in.readBoolean(),
-                            /* locationRequests= */
-                            in.createTypedArrayList(LocationRequest.CREATOR),
-                            /* workSource= */ in.readTypedObject(WorkSource.CREATOR));
+                    long intervalMillis = in.readLong();
+                    if (intervalMillis == INTERVAL_DISABLED) {
+                        return EMPTY_REQUEST;
+                    } else {
+                        return new ProviderRequest(
+                                intervalMillis,
+                                /* quality= */ in.readInt(),
+                                /* lowPower= */ in.readBoolean(),
+                                /* locationSettingsIgnored= */ in.readBoolean(),
+                                /* workSource= */ in.readTypedObject(WorkSource.CREATOR));
+                    }
                 }
 
                 @Override
@@ -140,10 +161,12 @@
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeLong(interval);
-        parcel.writeBoolean(mLowPower);
-        parcel.writeBoolean(mLocationSettingsIgnored);
-        parcel.writeTypedList(locationRequests);
-        parcel.writeTypedObject(mWorkSource, flags);
+        if (interval != INTERVAL_DISABLED) {
+            parcel.writeInt(mQuality);
+            parcel.writeBoolean(mLowPower);
+            parcel.writeBoolean(mLocationSettingsIgnored);
+            parcel.writeTypedObject(mWorkSource, flags);
+        }
     }
 
     @Override
@@ -160,16 +183,16 @@
             return that.interval == INTERVAL_DISABLED;
         } else {
             return interval == that.interval
+                    && mQuality == that.mQuality
                     && mLowPower == that.mLowPower
                     && mLocationSettingsIgnored == that.mLocationSettingsIgnored
-                    && locationRequests.equals(that.locationRequests)
                     && mWorkSource.equals(that.mWorkSource);
         }
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(interval, mWorkSource);
+        return Objects.hash(interval, mQuality, mWorkSource);
     }
 
     @Override
@@ -179,6 +202,13 @@
         if (interval != INTERVAL_DISABLED) {
             s.append("@");
             TimeUtils.formatDuration(interval, s);
+            if (mQuality != QUALITY_BALANCED_POWER_ACCURACY) {
+                if (mQuality == QUALITY_HIGH_ACCURACY) {
+                    s.append(", HIGH_ACCURACY");
+                } else if (mQuality == QUALITY_LOW_POWER) {
+                    s.append(", LOW_POWER");
+                }
+            }
             if (mLowPower) {
                 s.append(", lowPower");
             }
@@ -200,9 +230,9 @@
      */
     public static class Builder {
         private long mIntervalMillis = INTERVAL_DISABLED;
+        private int mQuality = QUALITY_BALANCED_POWER_ACCURACY;
         private boolean mLowPower;
         private boolean mLocationSettingsIgnored;
-        private List<LocationRequest> mLocationRequests = Collections.emptyList();
         private WorkSource mWorkSource = new WorkSource();
 
         /**
@@ -216,6 +246,20 @@
         }
 
         /**
+         * Sets the request quality. The quality is a hint to providers on how they should weigh
+         * power vs accuracy tradeoffs. High accuracy locations may cost more power to produce, and
+         * lower accuracy locations may cost less power to produce. Defaults to
+         * {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY}.
+         */
+        public @NonNull Builder setQuality(@Quality int quality) {
+            Preconditions.checkArgument(
+                    quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY
+                            || quality == QUALITY_HIGH_ACCURACY);
+            mQuality = quality;
+            return this;
+        }
+
+        /**
          * Sets whether hardware low power mode should be used. False by default.
          */
         public @NonNull Builder setLowPower(boolean lowPower) {
@@ -232,15 +276,6 @@
         }
 
         /**
-         * Sets the {@link LocationRequest}s associated with this request. Empty by default.
-         */
-        public @NonNull Builder setLocationRequests(
-                @NonNull List<LocationRequest> locationRequests) {
-            this.mLocationRequests = Objects.requireNonNull(locationRequests);
-            return this;
-        }
-
-        /**
          * Sets the work source for power blame. Empty by default.
          */
         public @NonNull Builder setWorkSource(@NonNull WorkSource workSource) {
@@ -255,8 +290,8 @@
             if (mIntervalMillis == INTERVAL_DISABLED) {
                 return EMPTY_REQUEST;
             } else {
-                return new ProviderRequest(mIntervalMillis, mLowPower, mLocationSettingsIgnored,
-                        mLocationRequests, mWorkSource);
+                return new ProviderRequest(mIntervalMillis, mQuality, mLowPower,
+                        mLocationSettingsIgnored, mWorkSource);
             }
         }
     }
diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt
index f43eb63..80636c6 100644
--- a/location/lib/api/current.txt
+++ b/location/lib/api/current.txt
@@ -29,18 +29,18 @@
     field public static final String FUSED_PROVIDER = "fused";
   }
 
-  public final class LocationRequestUnbundled {
-    method public long getFastestInterval();
-    method public long getInterval();
-    method public int getQuality();
-    method public float getSmallestDisplacement();
-    method public boolean isLocationSettingsIgnored();
-    field public static final int ACCURACY_BLOCK = 102; // 0x66
-    field public static final int ACCURACY_CITY = 104; // 0x68
-    field public static final int ACCURACY_FINE = 100; // 0x64
-    field public static final int POWER_HIGH = 203; // 0xcb
-    field public static final int POWER_LOW = 201; // 0xc9
-    field public static final int POWER_NONE = 200; // 0xc8
+  @Deprecated public final class LocationRequestUnbundled {
+    method @Deprecated public long getFastestInterval();
+    method @Deprecated public long getInterval();
+    method @Deprecated @android.location.LocationRequest.Quality public int getQuality();
+    method @Deprecated public float getSmallestDisplacement();
+    method @Deprecated public boolean isLocationSettingsIgnored();
+    field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
+    field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
+    field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
+    field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
+    field @Deprecated public static final int POWER_LOW = 201; // 0xc9
+    field @Deprecated public static final int POWER_NONE = 200; // 0xc8
   }
 
   public final class ProviderPropertiesUnbundled {
@@ -49,7 +49,8 @@
 
   public final class ProviderRequestUnbundled {
     method public long getInterval();
-    method @NonNull public java.util.List<com.android.location.provider.LocationRequestUnbundled> getLocationRequests();
+    method @Deprecated @NonNull public java.util.List<com.android.location.provider.LocationRequestUnbundled> getLocationRequests();
+    method @android.location.LocationRequest.Quality @RequiresApi(android.os.Build.VERSION_CODES.S) public int getQuality();
     method public boolean getReportLocation();
     method @NonNull @RequiresApi(android.os.Build.VERSION_CODES.S) public android.os.WorkSource getWorkSource();
     method @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isLocationSettingsIgnored();
diff --git a/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java b/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java
index 92e05ef..0e7c633 100644
--- a/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java
+++ b/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java
@@ -17,6 +17,7 @@
 package com.android.location.provider;
 
 import android.location.LocationRequest;
+import android.location.LocationRequest.Quality;
 
 /**
  * This class is an interface to LocationRequests for unbundled applications.
@@ -24,55 +25,50 @@
  * <p>IMPORTANT: This class is effectively a public API for unbundled
  * applications, and must remain API stable. See README.txt in the root
  * of this package for more information.
+ *
+ * @deprecated Do not use.
  */
+@Deprecated
 public final class LocationRequestUnbundled {
+
     /**
-     * Returned by {@link #getQuality} when requesting the most accurate locations available.
-     *
-     * <p>This may be up to 1 meter accuracy, although this is implementation dependent.
+     * @deprecated Use {@link LocationRequest#QUALITY_HIGH_ACCURACY} instead.
      */
+    @Deprecated
     public static final int ACCURACY_FINE = LocationRequest.ACCURACY_FINE;
 
     /**
-     * Returned by {@link #getQuality} when requesting "block" level accuracy.
-     *
-     * <p>Block level accuracy is considered to be about 100 meter accuracy,
-     * although this is implementation dependent. Using a coarse accuracy
-     * such as this often consumes less power.
+     * @deprecated Use {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY} instead.
      */
+    @Deprecated
     public static final int ACCURACY_BLOCK = LocationRequest.ACCURACY_BLOCK;
 
+
     /**
-     * Returned by {@link #getQuality} when requesting "city" level accuracy.
-     *
-     * <p>City level accuracy is considered to be about 10km accuracy,
-     * although this is implementation dependent. Using a coarse accuracy
-     * such as this often consumes less power.
+     * @deprecated Use {@link LocationRequest#QUALITY_LOW_POWER} instead.
      */
+    @Deprecated
     public static final int ACCURACY_CITY = LocationRequest.ACCURACY_CITY;
 
+
     /**
-     * Returned by {@link #getQuality} when requiring no direct power impact (passive locations).
-     *
-     * <p>This location request will not trigger any active location requests,
-     * but will receive locations triggered by other applications. Your application
-     * will not receive any direct power blame for location work.
+     * @deprecated Do not use.
      */
+    @Deprecated
     public static final int POWER_NONE = LocationRequest.POWER_NONE;
 
-    /**
-     * Returned by {@link #getQuality} when requesting low power impact.
-     *
-     * <p>This location request will avoid high power location work where
-     * possible.
-     */
-    public static final int POWER_LOW = LocationRequest.POWER_LOW;
 
     /**
-     * Returned by {@link #getQuality} when allowing high power consumption for location.
-     *
-     * <p>This location request will allow high power location work.
+     * @deprecated Use {@link LocationRequest#QUALITY_LOW_POWER} instead.
      */
+    @Deprecated
+    public static final int POWER_LOW = LocationRequest.POWER_LOW;
+
+
+    /**
+     * @deprecated Use {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY} instead.
+     */
+    @Deprecated
     public static final int POWER_HIGH = LocationRequest.POWER_HIGH;
 
     private final LocationRequest delegate;
@@ -102,9 +98,9 @@
     /**
      * Get the quality of the request.
      *
-     * @return an accuracy or power constant
+     * @return a {@link LocationRequest} QUALITY_* constant
      */
-    public int getQuality() {
+    public @Quality int getQuality() {
         return delegate.getQuality();
     }
 
diff --git a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
index 6f5fcc7..f7bac74 100644
--- a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
+++ b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
@@ -25,7 +25,7 @@
 
 import com.android.internal.location.ProviderRequest;
 
-import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -57,6 +57,16 @@
     }
 
     /**
+     * The quality hint for this location request. The quality hint informs the provider how it
+     * should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this
+     * provider request.
+     */
+    @RequiresApi(Build.VERSION_CODES.S)
+    public @LocationRequest.Quality int getQuality() {
+        return mRequest.getQuality();
+    }
+
+    /**
      * The interval at which a provider should report location. Will return
      * {@link #INTERVAL_DISABLED} for an inactive request.
      */
@@ -84,14 +94,22 @@
 
     /**
      * The full list of location requests contributing to this provider request.
+     *
+     * @deprecated Do not use.
      */
+    @Deprecated
     public @NonNull List<LocationRequestUnbundled> getLocationRequests() {
-        List<LocationRequestUnbundled> result = new ArrayList<>(
-                mRequest.getLocationRequests().size());
-        for (LocationRequest r : mRequest.getLocationRequests()) {
-            result.add(new LocationRequestUnbundled(r));
+        if (!mRequest.isActive()) {
+            return Collections.emptyList();
         }
-        return result;
+
+        return Collections.singletonList(new LocationRequestUnbundled(
+                new LocationRequest.Builder(mRequest.getIntervalMillis())
+                        .setQuality(mRequest.getQuality())
+                        .setLowPower(mRequest.isLowPower())
+                        .setLocationSettingsIgnored(mRequest.isLocationSettingsIgnored())
+                        .setWorkSource(mRequest.getWorkSource())
+                        .build()));
     }
 
     /**
diff --git a/media/java/android/media/tv/TunedInfo.java b/media/java/android/media/tv/TunedInfo.java
index 6fc5784..6199c89 100644
--- a/media/java/android/media/tv/TunedInfo.java
+++ b/media/java/android/media/tv/TunedInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -35,6 +36,7 @@
  * or pass-through input.
  * @hide
  */
+@SystemApi
 public final class TunedInfo implements Parcelable {
     static final String TAG = "TunedInfo";
 
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 73539fb..e9959be 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -906,8 +906,8 @@
          * @param tunedInfos a list of {@link TunedInfo} objects of new tuned information.
          * @hide
          */
-        public void onCurrentTunedInfosUpdated(
-                @NonNull List<TunedInfo> tunedInfos) {
+        @SystemApi
+        public void onCurrentTunedInfosUpdated(@NonNull List<TunedInfo> tunedInfos) {
         }
     }
 
@@ -969,7 +969,7 @@
             });
         }
 
-        public void onCurrentTunedInfosUpdated(final List<TunedInfo> currentTunedInfos) {
+        public void postCurrentTunedInfosUpdated(final List<TunedInfo> currentTunedInfos) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -1286,7 +1286,7 @@
             public void onCurrentTunedInfosUpdated(List<TunedInfo> currentTunedInfos) {
                 synchronized (mLock) {
                     for (TvInputCallbackRecord record : mCallbackRecords) {
-                        record.onCurrentTunedInfosUpdated(currentTunedInfos);
+                        record.postCurrentTunedInfosUpdated(currentTunedInfos);
                     }
                 }
             }
@@ -1988,6 +1988,7 @@
      * {@link TunedInfo#getChannelUri()} returns {@code null}.
      * @hide
      */
+    @SystemApi
     @RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS")
     @NonNull
     public List<TunedInfo> getCurrentTunedInfos() {
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 27a49a7..3252c90 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -122,10 +122,25 @@
             android.hardware.tv.tuner.V1_1.Constants.Constant
                     .INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM;
     /**
+     * Invalid local transport stream id.
+     *
+     * <p>Returned by {@link #linkFrontendToCiCam(int)} when the requested failed
+     * or the hal implementation does not support the operation.
+     *
+     * @see #linkFrontendToCiCam(int)
+     */
+    public static final int INVALID_LTS_ID =
+            android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LTS_ID;
+    /**
      * Invalid 64-bit filter ID.
      */
     public static final long INVALID_FILTER_ID_64BIT =
             android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_FILTER_ID_64BIT;
+    /**
+     * Invalid frequency that is used as the default frontend frequency setting.
+     */
+    public static final int INVALID_FRONTEND_SETTING_FREQUENCY =
+            android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FRONTEND_SETTING_FREQUENCY;
 
     /** @hide */
     @IntDef(prefix = "SCAN_TYPE_", value = {SCAN_TYPE_UNDEFINED, SCAN_TYPE_AUTO, SCAN_TYPE_BLIND})
@@ -475,7 +490,9 @@
     private native Integer nativeGetAvSyncHwId(Filter filter);
     private native Long nativeGetAvSyncTime(int avSyncId);
     private native int nativeConnectCiCam(int ciCamId);
+    private native int nativeLinkCiCam(int ciCamId);
     private native int nativeDisconnectCiCam();
+    private native int nativeUnlinkCiCam(int ciCamId);
     private native FrontendInfo nativeGetFrontendInfo(int id);
     private native Filter nativeOpenFilter(int type, int subType, long bufferSize);
     private native TimeFilter nativeOpenTimeFilter();
@@ -798,6 +815,33 @@
     }
 
     /**
+     * Link Conditional Access Modules (CAM) Frontend to support Common Interface (CI) by-pass mode.
+     *
+     * <p>It is used by the client to link CI-CAM to a Frontend. CI by-pass mode requires that
+     * the CICAM also receives the TS concurrently from the frontend when the Demux is receiving
+     * the TS directly from the frontend.
+     *
+     * <p>Use {@link #unlinkFrontendToCicam(int)} to disconnect.
+     *
+     * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+     * no-op and return {@link INVALID_LTS_ID}. Use {@link TunerVersionChecker.getTunerVersion()} to
+     * check the version.
+     *
+     * @param ciCamId specify CI-CAM Id to link.
+     * @return Local transport stream id when connection is successfully established. Failed
+     *         operation returns {@link INVALID_LTS_ID}.
+     */
+    public int linkFrontendToCiCam(int ciCamId) {
+        if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1,
+                "linkFrontendToCiCam")) {
+            if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) {
+                return nativeLinkCiCam(ciCamId);
+            }
+        }
+        return INVALID_LTS_ID;
+    }
+
+    /**
      * Disconnects Conditional Access Modules (CAM)
      *
      * <p>The demux will use the output from the frontend as the input after this call.
@@ -813,6 +857,28 @@
     }
 
     /**
+     * Unlink Conditional Access Modules (CAM) Frontend.
+     *
+     * <p>It is used by the client to unlink CI-CAM to a Frontend.
+     *
+     * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+     * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     *
+     * @param ciCamId specify CI-CAM Id to unlink.
+     * @return result status of the operation.
+     */
+    @Result
+    public int unlinkFrontendToCiCam(int ciCamId) {
+        if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1,
+                "unlinkFrontendToCiCam")) {
+            if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) {
+                return nativeUnlinkCiCam(ciCamId);
+            }
+        }
+        return RESULT_UNAVAILABLE;
+    }
+
+    /**
      * Gets the frontend information.
      *
      * @return The frontend information. {@code null} if the operation failed.
diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
index f54b686..2649fcf 100644
--- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.annotation.Size;
 import android.annotation.SystemApi;
+import android.media.tv.tuner.TunerVersionChecker;
 
 /**
  * Filter configuration for a IP filter.
@@ -28,20 +29,28 @@
  */
 @SystemApi
 public final class IpFilterConfiguration extends FilterConfiguration {
+    /**
+     * Undefined filter type.
+     */
+    public static final int INVALID_IP_FILTER_CONTEXT_ID =
+            android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_IP_FILTER_CONTEXT_ID;
+
     private final byte[] mSrcIpAddress;
     private final byte[] mDstIpAddress;
     private final int mSrcPort;
     private final int mDstPort;
     private final boolean mPassthrough;
+    private final int mIpFilterContextId;
 
     private IpFilterConfiguration(Settings settings, byte[] srcAddr, byte[] dstAddr, int srcPort,
-            int dstPort, boolean passthrough) {
+            int dstPort, boolean passthrough, int ipCid) {
         super(settings);
         mSrcIpAddress = srcAddr;
         mDstIpAddress = dstAddr;
         mSrcPort = srcPort;
         mDstPort = dstPort;
         mPassthrough = passthrough;
+        mIpFilterContextId = ipCid;
     }
 
     @Override
@@ -86,6 +95,15 @@
     public boolean isPassthrough() {
         return mPassthrough;
     }
+    /**
+     * Gets the ip filter context id. Default value is {@link #INVALID_IP_FILTER_CONTEXT_ID}.
+     *
+     * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would return
+     * default value. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     */
+    public int getIpFilterContextId() {
+        return mIpFilterContextId;
+    }
 
     /**
      * Creates a builder for {@link IpFilterConfiguration}.
@@ -105,6 +123,7 @@
         private int mDstPort = 0;
         private boolean mPassthrough = false;
         private Settings mSettings;
+        private int mIpCid = INVALID_IP_FILTER_CONTEXT_ID;
 
         private Builder() {
         }
@@ -170,6 +189,21 @@
         }
 
         /**
+         * Sets the ip filter context id. Default value is {@link #INVALID_IP_FILTER_CONTEXT_ID}.
+         *
+         * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         */
+        @NonNull
+        public Builder setIpFilterContextId(int ipContextId) {
+            if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                        TunerVersionChecker.TUNER_VERSION_1_1, "setIpFilterContextId")) {
+                mIpCid = ipContextId;
+            }
+            return this;
+        }
+
+        /**
          * Builds a {@link IpFilterConfiguration} object.
          */
         @NonNull
@@ -180,8 +214,8 @@
                     "The lengths of src and dst IP address must be 4 or 16 and must be the same."
                             + "srcLength=" + ipAddrLength + ", dstLength=" + mDstIpAddress.length);
             }
-            return new IpFilterConfiguration(
-                    mSettings, mSrcIpAddress, mDstIpAddress, mSrcPort, mDstPort, mPassthrough);
+            return new IpFilterConfiguration(mSettings, mSrcIpAddress, mDstIpAddress, mSrcPort,
+                    mDstPort, mPassthrough, mIpCid);
         }
     }
 }
diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
index 1d36da3..c6a5bb0 100644
--- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.TunerVersionChecker;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -164,9 +165,32 @@
      */
     public static final int SIF_L_PRIME = Constants.FrontendAnalogSifStandard.L_PRIME;
 
+    /** @hide */
+    @IntDef(prefix = "AFT_FLAG_",
+            value = {AFT_FLAG_UNDEFINED, AFT_FLAG_TRUE, AFT_FLAG_FALSE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AftFlag {}
+
+    /**
+     * Aft flag is not defined.
+     */
+    public static final int AFT_FLAG_UNDEFINED =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.UNDEFINED;
+    /**
+     * Aft flag is set true.
+     */
+    public static final int AFT_FLAG_TRUE =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_TRUE;
+    /**
+     * Aft flag is not set.
+     */
+    public static final int AFT_FLAG_FALSE =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_FALSE;
+
 
     private final int mSignalType;
     private final int mSifStandard;
+    private final int mAftFlag;
 
     @Override
     public int getType() {
@@ -191,6 +215,14 @@
     }
 
     /**
+     * Gets AFT flag.
+     */
+    @AftFlag
+    public int getAftFlag() {
+        return mAftFlag;
+    }
+
+    /**
      * Creates a builder for {@link AnalogFrontendSettings}.
      */
     @NonNull
@@ -198,10 +230,11 @@
         return new Builder();
     }
 
-    private AnalogFrontendSettings(int frequency, int signalType, int sifStandard) {
+    private AnalogFrontendSettings(int frequency, int signalType, int sifStandard, int aftFlag) {
         super(frequency);
         mSignalType = signalType;
         mSifStandard = sifStandard;
+        mAftFlag = aftFlag;
     }
 
     /**
@@ -211,6 +244,7 @@
         private int mFrequency = 0;
         private int mSignalType = SIGNAL_TYPE_UNDEFINED;
         private int mSifStandard = SIF_UNDEFINED;
+        private int mAftFlag = AFT_FLAG_UNDEFINED;
 
         private Builder() {}
 
@@ -227,6 +261,24 @@
         }
 
         /**
+         * Set Aft flag.
+         *
+         * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         *
+         * @param aftFlag the value to set the aft flag. The default value is
+         * {@link #AFT_FLAG_UNDEFINED}.
+         */
+        @NonNull
+        public Builder setAftFlag(@AftFlag int aftFlag) {
+            if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                    TunerVersionChecker.TUNER_VERSION_1_1, "setAftFlag")) {
+                mAftFlag = aftFlag;
+            }
+            return this;
+        }
+
+        /**
          * Sets analog signal type.
          *
          * <p>Default value is {@link #SIGNAL_TYPE_UNDEFINED}.
@@ -253,7 +305,7 @@
          */
         @NonNull
         public AnalogFrontendSettings build() {
-            return new AnalogFrontendSettings(mFrequency, mSignalType, mSifStandard);
+            return new AnalogFrontendSettings(mFrequency, mSignalType, mSifStandard, mAftFlag);
         }
     }
 }
diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
index f9eabc5..ed1ce2d 100644
--- a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
@@ -377,8 +377,8 @@
          */
         @NonNull
         public Atsc3FrontendSettings build() {
-            return new Atsc3FrontendSettings(
-                mFrequency, mBandwidth, mDemodOutputFormat, mPlpSettings);
+            return new Atsc3FrontendSettings(mFrequency, mBandwidth, mDemodOutputFormat,
+                    mPlpSettings);
         }
     }
 
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
index 271e91e..6732686 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
@@ -21,6 +21,8 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.TunerVersionChecker;
+import android.media.tv.tuner.frontend.FrontendSettings.FrontendSpectralInversion;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -140,6 +142,74 @@
     public static final int SPECTRAL_INVERSION_INVERTED =
             Constants.FrontendDvbcSpectralInversion.INVERTED;
 
+    /** @hide */
+    @IntDef(flag = true,
+            prefix = "TIME_INTERLEAVE_MODE_",
+            value = {TIME_INTERLEAVE_MODE_UNDEFINED, TIME_INTERLEAVE_MODE_AUTO,
+                    TIME_INTERLEAVE_MODE_128_1_0, TIME_INTERLEAVE_MODE_128_1_1,
+                    TIME_INTERLEAVE_MODE_64_2, TIME_INTERLEAVE_MODE_32_4,
+                    TIME_INTERLEAVE_MODE_16_8, TIME_INTERLEAVE_MODE_8_16,
+                    TIME_INTERLEAVE_MODE_128_2, TIME_INTERLEAVE_MODE_128_3,
+                    TIME_INTERLEAVE_MODE_128_4})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TimeInterleaveMode {}
+
+    /**
+     * Time interleave mode undefined.
+     */
+    public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.UNDEFINED;
+    /**
+     * Hardware is able to detect and set Time Interleave Mode automatically.
+     */
+    public static final int TIME_INTERLEAVE_MODE_AUTO =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.AUTO;
+    /**
+     * 128/1/0 Time Interleave Mode.
+     */
+    public static final int TIME_INTERLEAVE_MODE_128_1_0 = android.hardware.tv.tuner.V1_1.Constants
+            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_0;
+    /**
+     * 128/1/1 Time Interleave Mode.
+     */
+    public static final int TIME_INTERLEAVE_MODE_128_1_1 = android.hardware.tv.tuner.V1_1.Constants
+            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_1;
+    /**
+     * 64/2 Time Interleave Mode.
+     */
+    public static final int TIME_INTERLEAVE_MODE_64_2 = android.hardware.tv.tuner.V1_1.Constants
+            .FrontendCableTimeInterleaveMode.INTERLEAVING_64_2;
+    /**
+     * 32/4 Time Interleave Mode.
+     */
+    public static final int TIME_INTERLEAVE_MODE_32_4 = android.hardware.tv.tuner.V1_1.Constants
+            .FrontendCableTimeInterleaveMode.INTERLEAVING_32_4;
+    /**
+     * 16/8 Time Interleave Mode.
+     */
+    public static final int TIME_INTERLEAVE_MODE_16_8 = android.hardware.tv.tuner.V1_1.Constants
+            .FrontendCableTimeInterleaveMode.INTERLEAVING_16_8;
+    /**
+     * 8/16 Time Interleave Mode.
+     */
+    public static final int TIME_INTERLEAVE_MODE_8_16 = android.hardware.tv.tuner.V1_1.Constants
+            .FrontendCableTimeInterleaveMode.INTERLEAVING_8_16;
+    /**
+     * 128/2 Time Interleave Mode.
+     */
+    public static final int TIME_INTERLEAVE_MODE_128_2 = android.hardware.tv.tuner.V1_1.Constants
+            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_2;
+    /**
+     * 128/3 Time Interleave Mode.
+     */
+    public static final int TIME_INTERLEAVE_MODE_128_3 = android.hardware.tv.tuner.V1_1.Constants
+            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_3;
+    /**
+     * 128/4 Time Interleave Mode.
+     */
+    public static final int TIME_INTERLEAVE_MODE_128_4 = android.hardware.tv.tuner.V1_1.Constants
+            .FrontendCableTimeInterleaveMode.INTERLEAVING_128_4;
+
 
     private final int mModulation;
     private final long mInnerFec;
@@ -147,9 +217,11 @@
     private final int mOuterFec;
     private final int mAnnex;
     private final int mSpectralInversion;
+    // Dvbc time interleave mode is only supported in Tuner 1.1 or higher.
+    private final int mInterleaveMode;
 
     private DvbcFrontendSettings(int frequency, int modulation, long innerFec, int symbolRate,
-            int outerFec, int annex, int spectralInversion) {
+            int outerFec, int annex, int spectralInversion, int interleaveMode) {
         super(frequency);
         mModulation = modulation;
         mInnerFec = innerFec;
@@ -157,6 +229,7 @@
         mOuterFec = outerFec;
         mAnnex = annex;
         mSpectralInversion = spectralInversion;
+        mInterleaveMode = interleaveMode;
     }
 
     /**
@@ -196,10 +269,17 @@
     /**
      * Gets Spectral Inversion.
      */
-    @SpectralInversion
+    @FrontendSpectralInversion
     public int getSpectralInversion() {
         return mSpectralInversion;
     }
+    /**
+     * Gets Time Interleave Mode.
+     */
+    @TimeInterleaveMode
+    public int getTimeInterleaveMode() {
+        return mInterleaveMode;
+    }
 
     /**
      * Creates a builder for {@link DvbcFrontendSettings}.
@@ -219,7 +299,8 @@
         private int mSymbolRate = 0;
         private int mOuterFec = OUTER_FEC_UNDEFINED;
         private int mAnnex = ANNEX_UNDEFINED;
-        private int mSpectralInversion = SPECTRAL_INVERSION_UNDEFINED;
+        private int mSpectralInversion = FrontendSettings.FRONTEND_SPECTRAL_INVERSION_UNDEFINED;
+        private int mInterleaveMode = TIME_INTERLEAVE_MODE_UNDEFINED;
 
         private Builder() {
         }
@@ -289,13 +370,30 @@
         /**
          * Sets Spectral Inversion.
          *
-         * <p>Default value is {@link #SPECTRAL_INVERSION_UNDEFINED}.
+         * <p>Default value is {@link FrontendSettings#FRONTEND_SPECTRAL_INVERSION_UNDEFINED}.
          */
         @NonNull
-        public Builder setSpectralInversion(@SpectralInversion int spectralInversion) {
+        public Builder setSpectralInversion(@FrontendSpectralInversion int spectralInversion) {
             mSpectralInversion = spectralInversion;
             return this;
         }
+        /**
+         * Set the time interleave mode.
+         *
+         * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         *
+         * @param interleaveMode the value to set as the time interleave mode. Default value is
+         * {@link #TIME_INTERLEAVE_MODE_UNDEFINED}.
+         */
+        @NonNull
+        public Builder setTimeInterleaveMode(@TimeInterleaveMode int interleaveMode) {
+            if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                        TunerVersionChecker.TUNER_VERSION_1_1, "setTimeInterleaveMode")) {
+                mInterleaveMode = interleaveMode;
+            }
+            return this;
+        }
 
         /**
          * Builds a {@link DvbcFrontendSettings} object.
@@ -303,7 +401,7 @@
         @NonNull
         public DvbcFrontendSettings build() {
             return new DvbcFrontendSettings(mFrequency, mModulation, mInnerFec, mSymbolRate,
-                mOuterFec, mAnnex, mSpectralInversion);
+                mOuterFec, mAnnex, mSpectralInversion, mInterleaveMode);
         }
     }
 
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index 60b070f..343dbb1 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -23,6 +23,8 @@
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.Tuner;
+import android.media.tv.tuner.TunerVersionChecker;
+
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -36,6 +38,44 @@
 public class DvbsFrontendSettings extends FrontendSettings {
     /** @hide */
     @IntDef(flag = true,
+            prefix = "SCAN_TYPE_",
+            value = {SCAN_TYPE_UNDEFINED, SCAN_TYPE_DIRECT, SCAN_TYPE_DISEQC,
+                    SCAN_TYPE_UNICABLE, SCAN_TYPE_JESS})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ScanType {}
+
+    /**
+     * Dvbs scan type undefined.
+     */
+    public static final int SCAN_TYPE_UNDEFINED =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNDEFINED;
+
+    /**
+     * Dvbs scan type DIRECT.
+     */
+    public static final int SCAN_TYPE_DIRECT =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DIRECT;
+
+    /**
+     * Dvbs scan type DISEQC.
+     */
+    public static final int SCAN_TYPE_DISEQC =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DISEQC;
+
+    /**
+     * Dvbs scan type UNICABLE.
+     */
+    public static final int SCAN_TYPE_UNICABLE =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNICABLE;
+
+    /**
+     * Dvbs scan type JESS.
+     */
+    public static final int SCAN_TYPE_JESS =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.JESS;
+
+    /** @hide */
+    @IntDef(flag = true,
             prefix = "MODULATION_",
             value = {MODULATION_UNDEFINED, MODULATION_AUTO, MODULATION_MOD_QPSK,
                     MODULATION_MOD_8PSK, MODULATION_MOD_16QAM, MODULATION_MOD_16PSK,
@@ -218,9 +258,12 @@
     private final int mInputStreamId;
     private final int mStandard;
     private final int mVcmMode;
+    // Dvbs scan type is only supported in Tuner 1.1 or higher.
+    private final int mScanType;
 
     private DvbsFrontendSettings(int frequency, int modulation, DvbsCodeRate codeRate,
-            int symbolRate, int rolloff, int pilot, int inputStreamId, int standard, int vcm) {
+            int symbolRate, int rolloff, int pilot, int inputStreamId, int standard, int vcm,
+            int scanType) {
         super(frequency);
         mModulation = modulation;
         mCodeRate = codeRate;
@@ -230,6 +273,7 @@
         mInputStreamId = inputStreamId;
         mStandard = standard;
         mVcmMode = vcm;
+        mScanType = scanType;
     }
 
     /**
@@ -286,6 +330,13 @@
     public int getVcmMode() {
         return mVcmMode;
     }
+    /**
+     * Get scan type.
+     */
+    @ScanType
+    public int getScanType() {
+        return mScanType;
+    }
 
     /**
      * Creates a builder for {@link DvbsFrontendSettings}.
@@ -308,6 +359,7 @@
         private int mInputStreamId = Tuner.INVALID_STREAM_ID;
         private int mStandard = STANDARD_AUTO;
         private int mVcmMode = VCM_MODE_UNDEFINED;
+        private int mScanType = SCAN_TYPE_UNDEFINED;
 
         private Builder() {
         }
@@ -325,6 +377,24 @@
         }
 
         /**
+         * Set the scan type.
+         *
+         * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         *
+         * @param scanType the value to set as the scan type. Default value is
+         * {@link android.media.tv.tuner.frontend.DvbsFrontendSettings#DVBS_SCAN_TYPE_UNDEFINED}.
+         */
+        @NonNull
+        public Builder setScanType(@ScanType int scanType) {
+            if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                        TunerVersionChecker.TUNER_VERSION_1_1, "setScanType")) {
+                mScanType = scanType;
+            }
+            return this;
+        }
+
+        /**
          * Sets Modulation.
          *
          * <p>Default value is {@link #MODULATION_UNDEFINED}.
@@ -411,7 +481,7 @@
         @NonNull
         public DvbsFrontendSettings build() {
             return new DvbsFrontendSettings(mFrequency, mModulation, mCodeRate, mSymbolRate,
-                    mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode);
+                    mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode, mScanType);
         }
     }
 
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
index 5c057de..07d1797 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.TunerVersionChecker;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -75,8 +76,21 @@
      * 32K Transmission Mode.
      */
     public static final int TRANSMISSION_MODE_32K = Constants.FrontendDvbtTransmissionMode.MODE_32K;
-
-
+    /**
+     * 8K Transmission Extended Mode.
+     */
+    public static final int TRANSMISSION_MODE_EXTENDED_8K =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_8K_E;
+    /**
+     * 16K Transmission Extended Mode.
+     */
+    public static final int TRANSMISSION_MODE_EXTENDED_16K =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_16K_E;
+    /**
+     * 32K Transmission Extended Mode.
+     */
+    public static final int TRANSMISSION_MODE_EXTENDED_32K =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_32K_E;
 
     /** @hide */
     @IntDef(flag = true,
@@ -124,8 +138,9 @@
     @IntDef(flag = true,
             prefix = "CONSTELLATION_",
             value = {CONSTELLATION_UNDEFINED, CONSTELLATION_AUTO, CONSTELLATION_QPSK,
-                    CONSTELLATION_16QAM, CONSTELLATION_64QAM,
-                    CONSTELLATION_256QAM})
+                    CONSTELLATION_16QAM, CONSTELLATION_64QAM, CONSTELLATION_256QAM,
+                    CONSTELLATION_QPSK_R, CONSTELLATION_16QAM_R, CONSTELLATION_64QAM_R,
+                    CONSTELLATION_256QAM_R})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Constellation {}
 
@@ -157,7 +172,30 @@
      */
     public static final int CONSTELLATION_256QAM =
             Constants.FrontendDvbtConstellation.CONSTELLATION_256QAM;
-
+    /**
+     * QPSK Rotated Constellation.
+     */
+    public static final int CONSTELLATION_QPSK_R =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
+                    .CONSTELLATION_QPSK_R;
+    /**
+     * 16QAM Rotated Constellation.
+     */
+    public static final int CONSTELLATION_16QAM_R =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
+                    .CONSTELLATION_16QAM_R;
+    /**
+     * 64QAM Rotated Constellation.
+     */
+    public static final int CONSTELLATION_64QAM_R =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
+                    .CONSTELLATION_64QAM_R;
+    /**
+     * 256QAM Rotated Constellation.
+     */
+    public static final int CONSTELLATION_256QAM_R =
+            android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
+                    .CONSTELLATION_256QAM_R;
 
     /** @hide */
     @IntDef(flag = true,
@@ -366,8 +404,7 @@
      */
     public static final int PLP_MODE_MANUAL = Constants.FrontendDvbtPlpMode.MANUAL;
 
-
-    private final int mTransmissionMode;
+    private int mTransmissionMode;
     private final int mBandwidth;
     private final int mConstellation;
     private final int mHierarchy;
@@ -489,6 +526,19 @@
         return mPlpGroupId;
     }
 
+    private static boolean isExtendedTransmissionMode(@TransmissionMode int transmissionMode) {
+        return transmissionMode == TRANSMISSION_MODE_EXTENDED_8K
+                || transmissionMode == TRANSMISSION_MODE_EXTENDED_16K
+                || transmissionMode == TRANSMISSION_MODE_EXTENDED_32K;
+    }
+
+    private static boolean isExtendedConstellation(@Constellation int constellation) {
+        return constellation == CONSTELLATION_QPSK_R
+                || constellation == CONSTELLATION_16QAM_R
+                || constellation == CONSTELLATION_64QAM_R
+                || constellation == CONSTELLATION_256QAM_R;
+    }
+
     /**
      * Creates a builder for {@link DvbtFrontendSettings}.
      */
@@ -534,13 +584,23 @@
         /**
          * Sets Transmission Mode.
          *
+         * <p>{@link #TRANSMISSION_MODE_EXTENDED_8K}, {@link #TRANSMISSION_MODE_EXTENDED_16K} and
+         * {@link #TRANSMISSION_MODE_EXTENDED_32K} are only supported by Tuner HAL 1.1 or higher.
+         * Unsupported version would cause no-op. Use {@link TunerVersionChecker.getTunerVersion()}
+         * to check the version.
+         *
          * <p>Default value is {@link #TRANSMISSION_MODE_UNDEFINED}.
          */
         @NonNull
         public Builder setTransmissionMode(@TransmissionMode int transmissionMode) {
-            mTransmissionMode = transmissionMode;
+            if (!isExtendedTransmissionMode(transmissionMode)
+                    || TunerVersionChecker.checkHigherOrEqualVersionTo(
+                            TunerVersionChecker.TUNER_VERSION_1_1, "set TransmissionMode Ext")) {
+                mTransmissionMode = transmissionMode;
+            }
             return this;
         }
+
         /**
          * Sets Bandwidth.
          *
@@ -554,11 +614,20 @@
         /**
          * Sets Constellation.
          *
+         * <p>{@link #CONSTELLATION_QPSK_R}, {@link #CONSTELLATION_16QAM_R},
+         * {@link #CONSTELLATION_64QAM_R} and {@link #CONSTELLATION_256QAM_Rare} are only supported
+         * by Tuner HAL 1.1 or higher. Unsupported version would cause no-op. Use
+         * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         *
          * <p>Default value is {@link #CONSTELLATION_UNDEFINED}.
          */
         @NonNull
         public Builder setConstellation(@Constellation int constellation) {
-            mConstellation = constellation;
+            if (!isExtendedConstellation(constellation)
+                    || TunerVersionChecker.checkHigherOrEqualVersionTo(
+                            TunerVersionChecker.TUNER_VERSION_1_1, "set Constellation Ext")) {
+                mConstellation = constellation;
+            }
             return this;
         }
         /**
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
index 2f2fa97..82f7afa 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
@@ -17,9 +17,12 @@
 package android.media.tv.tuner.frontend;
 
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.LongDef;
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.Tuner;
+import android.media.tv.tuner.TunerVersionChecker;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -241,9 +244,36 @@
      */
     public static final long FEC_77_90 = Constants.FrontendInnerFec.FEC_77_90;
 
+    /** @hide */
+    @IntDef(prefix = "FRONTEND_SPECTRAL_INVERSION_",
+            value = {FRONTEND_SPECTRAL_INVERSION_UNDEFINED, FRONTEND_SPECTRAL_INVERSION_NORMAL,
+                    FRONTEND_SPECTRAL_INVERSION_INVERTED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FrontendSpectralInversion {}
+
+    /**
+     * Spectral Inversion Type undefined.
+     */
+    public static final int FRONTEND_SPECTRAL_INVERSION_UNDEFINED =
+            Constants.FrontendDvbcSpectralInversion.UNDEFINED;
+    /**
+     * Normal Spectral Inversion.
+     */
+    public static final int FRONTEND_SPECTRAL_INVERSION_NORMAL =
+            Constants.FrontendDvbcSpectralInversion.NORMAL;
+    /**
+     * Inverted Spectral Inversion.
+     */
+    public static final int FRONTEND_SPECTRAL_INVERSION_INVERTED =
+            Constants.FrontendDvbcSpectralInversion.INVERTED;
+
 
 
     private final int mFrequency;
+    // End frequency is only supported in Tuner 1.1 or higher.
+    private int mEndFrequency = Tuner.INVALID_FRONTEND_SETTING_FREQUENCY;
+    // General spectral inversion is only supported in Tuner 1.1 or higher.
+    private int mSpectralInversion = FRONTEND_SPECTRAL_INVERSION_UNDEFINED;
 
     FrontendSettings(int frequency) {
         mFrequency = frequency;
@@ -263,4 +293,57 @@
     public int getFrequency() {
         return mFrequency;
     }
+
+    /**
+     * Get the end frequency.
+     *
+     * @return the end frequency in Hz.
+     */
+    public int getEndFrequency() {
+        return mEndFrequency;
+    }
+
+    /**
+     * Get the spectral inversion.
+     *
+     * @return the value of the spectral inversion.
+     */
+    @FrontendSpectralInversion
+    public int getFrontendSpectralInversion() {
+        return mSpectralInversion;
+    }
+
+    /**
+     * Set Spectral Inversion.
+     *
+     * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+     * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     *
+     * @param inversion the value to set as the spectral inversion. Default value is {@link
+     * #FRONTEND_SPECTRAL_INVERSION_UNDEFINED}.
+     */
+    public void setSpectralInversion(@FrontendSpectralInversion int inversion) {
+        if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "setSpectralInversion")) {
+            mSpectralInversion = inversion;
+        }
+    }
+
+    /**
+     * Set End Frequency. This API is only supported with Tuner HAL 1.1 or higher. Otherwise it
+     * would be no-op.
+     *
+     * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+     * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     *
+     * @param endFrequency the end frequency used during blind scan. The default value is
+     * {@link android.media.tv.tuner.Tuner#INVALID_FRONTEND_SETTING_FREQUENCY}.
+     */
+    @IntRange(from = 1)
+    public void setEndFrequency(int endFrequency) {
+        if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                TunerVersionChecker.TUNER_VERSION_1_1, "setEndFrequency")) {
+            mEndFrequency = endFrequency;
+        }
+    }
 }
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index 2ef7b9e..b6c47fca 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -140,6 +140,27 @@
     fmt = applyFormatOverrides(fmt, containerFormat);
     switch (fmt) {
         case HAL_PIXEL_FORMAT_YCbCr_420_888:
+            // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
+            if (buffer->width % 2 != 0) {
+                ALOGE("YCbCr_420_888: width (%d) should be a multiple of 2", buffer->width);
+                return BAD_VALUE;
+            }
+
+            if (buffer->height % 2 != 0) {
+                ALOGE("YCbCr_420_888: height (%d) should be a multiple of 2", buffer->height);
+                return BAD_VALUE;
+            }
+
+            if (buffer->width <= 0) {
+                ALOGE("YCbCr_420_888: width (%d) should be a > 0", buffer->width);
+                return BAD_VALUE;
+            }
+
+            if (buffer->height <= 0) {
+                ALOGE("YCbCr_420_888: height (%d) should be a > 0", buffer->height);
+                return BAD_VALUE;
+            }
+
             pData =
                 (idx == 0) ?
                     buffer->data :
@@ -160,6 +181,27 @@
             break;
         // NV21
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
+            if (buffer->width % 2 != 0) {
+                ALOGE("YCrCb_420_SP: width (%d) should be a multiple of 2", buffer->width);
+                return BAD_VALUE;
+            }
+
+            if (buffer->height % 2 != 0) {
+                ALOGE("YCrCb_420_SP: height (%d) should be a multiple of 2", buffer->height);
+                return BAD_VALUE;
+            }
+
+            if (buffer->width <= 0) {
+                ALOGE("YCrCb_420_SP: width (%d) should be a > 0", buffer->width);
+                return BAD_VALUE;
+            }
+
+            if (buffer->height <= 0) {
+                ALOGE("YCrCb_420_SP: height (%d) should be a > 0", buffer->height);
+                return BAD_VALUE;
+            }
+
             cr = buffer->data + (buffer->stride * buffer->height);
             cb = cr + 1;
             // only map until last pixel
@@ -178,6 +220,27 @@
             rStride = buffer->width;
             break;
         case HAL_PIXEL_FORMAT_YV12:
+            // Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.
+            if (buffer->width % 2 != 0) {
+                ALOGE("YV12: width (%d) should be a multiple of 2", buffer->width);
+                return BAD_VALUE;
+            }
+
+            if (buffer->height % 2 != 0) {
+                ALOGE("YV12: height (%d) should be a multiple of 2", buffer->height);
+                return BAD_VALUE;
+            }
+
+            if (buffer->width <= 0) {
+                ALOGE("YV12: width (%d) should be a > 0", buffer->width);
+                return BAD_VALUE;
+            }
+
+            if (buffer->height <= 0) {
+                ALOGE("YV12: height (%d) should be a > 0", buffer->height);
+                return BAD_VALUE;
+            }
+
             // Y and C stride need to be 16 pixel aligned.
             LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
                                 "Stride is not 16 pixel aligned %d", buffer->stride);
@@ -344,6 +407,11 @@
     int flexFormat = format;
     if (isPossiblyYUV(format)) {
         res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);
+
+        if (res != OK) {
+            ALOGW("lockAsyncYCbCr failed with error %d", res);
+        }
+
         pData = ycbcr.y;
         flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
     }
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index e0afe29..979dc06 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -134,6 +134,14 @@
 using ::android::hardware::tv::tuner::V1_0::RecordSettings;
 using ::android::hardware::tv::tuner::V1_1::Constant;
 using ::android::hardware::tv::tuner::V1_1::Constant64Bit;
+using ::android::hardware::tv::tuner::V1_1::FrontendAnalogAftFlag;
+using ::android::hardware::tv::tuner::V1_1::FrontendAnalogSettingsExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode;
+using ::android::hardware::tv::tuner::V1_1::FrontendDvbsScanType;
+using ::android::hardware::tv::tuner::V1_1::FrontendDvbcSettingsExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendDvbsSettingsExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendDvbtSettingsExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendSpectralInversion;
 
 struct fields_t {
     jfieldID tunerContext;
@@ -309,9 +317,9 @@
 
 /////////////// MediaEvent ///////////////////////
 
-MediaEvent::MediaEvent(sp<IFilter> iFilter, hidl_handle avHandle,
-        uint64_t dataId, uint64_t dataLength, jobject obj) : mIFilter(iFilter),
-        mDataId(dataId), mDataLength(dataLength), mBuffer(nullptr),
+MediaEvent::MediaEvent(sp<Filter> filter, hidl_handle avHandle,
+        uint64_t dataId, uint64_t dataSize, jobject obj) : mFilter(filter),
+        mDataId(dataId), mDataSize(dataSize), mBuffer(nullptr),
         mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     mMediaEventObj = env->NewWeakGlobalRef(obj);
@@ -335,7 +343,8 @@
 
 void MediaEvent::finalize() {
     if (mAvHandleRefCnt == 0) {
-        mIFilter->releaseAvHandle(hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0);
+        mFilter->mFilterSp->releaseAvHandle(
+                hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0);
         native_handle_close(mAvHandle);
     }
 }
@@ -348,7 +357,47 @@
     if (mLinearBlockObj != NULL) {
         return mLinearBlockObj;
     }
-    mIonHandle = new C2HandleIon(dup(mAvHandle->data[0]), mDataLength);
+
+    int fd;
+    int numInts = 0;
+    int memIndex;
+    int dataSize;
+    if (mAvHandle->numFds == 0) {
+        if (mFilter->mAvSharedHandle == NULL) {
+            ALOGE("Shared AV memory handle is not initialized.");
+            return NULL;
+        }
+        if (mFilter->mAvSharedHandle->numFds == 0) {
+            ALOGE("Shared AV memory handle is empty.");
+            return NULL;
+        }
+        fd = mFilter->mAvSharedHandle->data[0];
+        dataSize = mFilter->mAvSharedMemSize;
+        numInts = mFilter->mAvSharedHandle->numInts;
+        if (numInts > 0) {
+            // If the first int in the shared native handle has value, use it as the index
+            memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds];
+        }
+    } else {
+        fd = mAvHandle->data[0];
+        dataSize = mDataSize;
+        numInts = mAvHandle->numInts;
+        if (numInts > 0) {
+            // Otherwise if the first int in the av native handle returned from the filter
+            // event has value, use it as the index
+            memIndex = mAvHandle->data[mAvHandle->numFds];
+        } else {
+            if (mFilter->mAvSharedHandle != NULL) {
+                numInts = mFilter->mAvSharedHandle->numInts;
+                if (numInts > 0) {
+                    // If the first int in the shared native handle has value, use it as the index
+                    memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds];
+                }
+            }
+        }
+    }
+
+    mIonHandle = new C2HandleIon(dup(fd), dataSize);
     std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(mIonHandle);
     if (block != nullptr) {
         // CreateLinearBlock delete mIonHandle after it create block successfully.
@@ -357,13 +406,11 @@
         JNIEnv *env = AndroidRuntime::getJNIEnv();
         std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock};
         context->mBlock = block;
-        std::shared_ptr<C2Buffer> pC2Buffer = context->toC2Buffer(0, mDataLength);
+        std::shared_ptr<C2Buffer> pC2Buffer = context->toC2Buffer(0, dataSize);
         context->mBuffer = pC2Buffer;
         mC2Buffer = pC2Buffer;
-        if (mAvHandle->numInts > 0) {
-            // use first int in the native_handle as the index
-            int index = mAvHandle->data[mAvHandle->numFds];
-            std::shared_ptr<C2Param> c2param = std::make_shared<C2DataIdInfo>(index, mDataId);
+        if (numInts > 0) {
+            std::shared_ptr<C2Param> c2param = std::make_shared<C2DataIdInfo>(memIndex, mDataId);
             std::shared_ptr<C2Info> info(std::static_pointer_cast<C2Info>(c2param));
             pC2Buffer->setInfo(info);
         }
@@ -470,7 +517,7 @@
 
         if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) {
             sp<MediaEvent> mediaEventSp =
-                           new MediaEvent(mIFilter, mediaEvent.avMemory,
+                           new MediaEvent(mFilter, mediaEvent.avMemory,
                                mediaEvent.avDataId, dataLength + offset, obj);
             mediaEventSp->mAvHandleRefCnt++;
             env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get());
@@ -690,7 +737,7 @@
         }
     }
     env->CallVoidMethod(
-            mFilter,
+            mFilter->mFilterObj,
             gFields.onFilterEventID,
             array);
     return Void();
@@ -709,7 +756,7 @@
     ALOGD("FilterCallback::onFilterStatus");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     env->CallVoidMethod(
-            mFilter,
+            mFilter->mFilterObj,
             gFields.onFilterStatusID,
             (jint)status);
     return Void();
@@ -717,17 +764,11 @@
 
 void FilterCallback::setFilter(const sp<Filter> filter) {
     ALOGD("FilterCallback::setFilter");
-    mFilter = filter->mFilterObj;
-    mIFilter = filter->mFilterSp;
+    // JNI Object
+    mFilter = filter;
 }
 
-FilterCallback::~FilterCallback() {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    if (mFilter != NULL) {
-        env->DeleteWeakGlobalRef(mFilter);
-        mFilter = NULL;
-    }
-}
+FilterCallback::~FilterCallback() {}
 
 /////////////// Filter ///////////////////////
 
@@ -1034,6 +1075,7 @@
         return NULL;
     }
     mFe = fe;
+    mFe_1_1 = ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe);
     mFeId = id;
     if (mDemux != NULL) {
         mDemux->setFrontendDataSource(mFeId);
@@ -1343,12 +1385,21 @@
     return lnbObj;
 }
 
-int JTuner::tune(const FrontendSettings& settings) {
+int JTuner::tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1) {
     if (mFe == NULL) {
         ALOGE("frontend is not initialized");
         return (int)Result::INVALID_STATE;
     }
-    Result result = mFe->tune(settings);
+    Result result;
+    sp<::android::hardware::tv::tuner::V1_1::IFrontend> fe_1_1 =
+            ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe);
+    if (fe_1_1 == NULL) {
+        ALOGD("1.1 frontend is not found. Using 1.0 instead.");
+        result = mFe->tune(settings);
+        return (int)result;
+    }
+
+    result = fe_1_1->tune_1_1(settings, settingsExt1_1);
     return (int)result;
 }
 
@@ -1361,12 +1412,22 @@
     return (int)result;
 }
 
-int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType) {
+int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType,
+        const FrontendSettingsExt1_1& settingsExt1_1) {
     if (mFe == NULL) {
         ALOGE("frontend is not initialized");
         return (int)Result::INVALID_STATE;
     }
-    Result result = mFe->scan(settings, scanType);
+    Result result;
+    sp<::android::hardware::tv::tuner::V1_1::IFrontend> fe_1_1 =
+            ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe);
+    if (fe_1_1 == NULL) {
+        ALOGD("1.1 frontend is not found. Using 1.0 instead.");
+        result = mFe->scan(settings, scanType);
+        return (int)result;
+    }
+
+    result = fe_1_1->scan_1_1(settings, scanType, settingsExt1_1);
     return (int)result;
 }
 
@@ -1493,6 +1554,27 @@
     return (int) r;
 }
 
+int JTuner::linkCiCam(int id) {
+    if (mFe_1_1 == NULL) {
+        ALOGE("frontend 1.1 is not initialized");
+        return (int)Constant::INVALID_LTS_ID;
+    }
+
+    Result res;
+    uint32_t ltsId;
+    mFe_1_1->linkCiCam(static_cast<uint32_t>(id),
+            [&](Result r, uint32_t id) {
+                res = r;
+                ltsId = id;
+            });
+
+    if (res != Result::SUCCESS) {
+        return (int)Constant::INVALID_LTS_ID;
+    }
+
+    return (int) ltsId;
+}
+
 int JTuner::disconnectCiCam() {
     if (mDemux == NULL) {
         Result r = openDemux();
@@ -1504,6 +1586,18 @@
     return (int) r;
 }
 
+
+int JTuner::unlinkCiCam(int id) {
+    if (mFe_1_1 == NULL) {
+        ALOGE("frontend 1.1 is not initialized");
+        return (int)Result::INVALID_STATE;
+    }
+
+    Result r = mFe_1_1->unlinkCiCam(static_cast<uint32_t>(id));
+
+    return (int) r;
+}
+
 jobject JTuner::openDescrambler() {
     ALOGD("JTuner::openDescrambler");
     if (mTuner == nullptr || mDemux == nullptr) {
@@ -1575,9 +1669,33 @@
     sp<Filter> filterSp = new Filter(iFilterSp, filterObj);
     filterSp->incStrong(filterObj);
     env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get());
-
+    filterSp->mIsMediaFilter = false;
+    filterSp->mAvSharedHandle = NULL;
     callback->setFilter(filterSp);
 
+    if (type.mainType == DemuxFilterMainType::MMTP) {
+        if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+                type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+            filterSp->mIsMediaFilter = true;
+        }
+    }
+
+    if (type.mainType == DemuxFilterMainType::TS) {
+        if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+                type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+            filterSp->mIsMediaFilter = true;
+        }
+    }
+
+    if (iFilterSp_1_1 != NULL && filterSp->mIsMediaFilter) {
+        iFilterSp_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
+            if (r == Result::SUCCESS) {
+                filterSp->mAvSharedHandle = native_handle_clone(avMemory.getNativeHandle());
+                filterSp->mAvSharedMemSize = avMemSize;
+            }
+        });
+    }
+
     return filterObj;
 }
 
@@ -1947,6 +2065,10 @@
     if (mFe != NULL) {
         r = mFe->close();
     }
+    if (r == Result::SUCCESS) {
+        mFe = NULL;
+        mFe_1_1 = NULL;
+    }
     return (jint) r;
 }
 
@@ -1955,6 +2077,9 @@
     if (mDemux != NULL) {
         r = mDemux->close();
     }
+    if (r == Result::SUCCESS) {
+        mDemux = NULL;
+    }
     return (jint) r;
 }
 
@@ -2007,6 +2132,22 @@
     return freq;
 }
 
+static uint32_t getFrontendSettingsEndFreq(JNIEnv *env, const jobject& settings) {
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings");
+    jfieldID endFreqField = env->GetFieldID(clazz, "mEndFrequency", "I");
+    uint32_t endFreq = static_cast<uint32_t>(env->GetIntField(settings, endFreqField));
+    return endFreq;
+}
+
+static FrontendSpectralInversion getFrontendSettingsSpectralInversion(
+        JNIEnv *env, const jobject& settings) {
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings");
+    jfieldID inversionField = env->GetFieldID(clazz, "mSpectralInversion", "I");
+    FrontendSpectralInversion inversion =
+            static_cast<FrontendSpectralInversion>(env->GetIntField(settings, inversionField));
+    return inversion;
+}
+
 static FrontendSettings getAnalogFrontendSettings(JNIEnv *env, const jobject& settings) {
     FrontendSettings frontendSettings;
     uint32_t freq = getFrontendSettingsFreq(env, settings);
@@ -2026,6 +2167,18 @@
     return frontendSettings;
 }
 
+static void getAnalogFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings,
+        FrontendSettingsExt1_1& settingsExt1_1) {
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings");
+    FrontendAnalogAftFlag aftFlag =
+            static_cast<FrontendAnalogAftFlag>(
+                    env->GetIntField(settings, env->GetFieldID(clazz, "mAftFlag", "I")));
+    FrontendAnalogSettingsExt1_1 analogExt1_1 {
+        .aftFlag = aftFlag,
+    };
+    settingsExt1_1.settingExt.analog(analogExt1_1);
+}
+
 static hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings(
         JNIEnv *env, const jobject& settings) {
     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings");
@@ -2145,6 +2298,19 @@
     return frontendSettings;
 }
 
+static void getDvbcFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings,
+        FrontendSettingsExt1_1& settingsExt1_1) {
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendSettings");
+    FrontendCableTimeInterleaveMode interleaveMode =
+            static_cast<FrontendCableTimeInterleaveMode>(
+                    env->GetIntField(settings, env->GetFieldID(clazz, "mInterleaveMode", "I")));
+
+    FrontendDvbcSettingsExt1_1 dvbcExt1_1 {
+        .interleaveMode = interleaveMode,
+    };
+    settingsExt1_1.settingExt.dvbc(dvbcExt1_1);
+}
+
 static FrontendDvbsCodeRate getDvbsCodeRate(JNIEnv *env, const jobject& settings) {
     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
     jobject jcodeRate =
@@ -2186,7 +2352,6 @@
     uint32_t freq = getFrontendSettingsFreq(env, settings);
     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
 
-
     FrontendDvbsModulation modulation =
             static_cast<FrontendDvbsModulation>(
                     env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
@@ -2225,6 +2390,22 @@
     return frontendSettings;
 }
 
+static void getDvbsFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings,
+        FrontendSettingsExt1_1& settingsExt1_1) {
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
+    FrontendDvbsScanType scanType =
+            static_cast<FrontendDvbsScanType>(
+                    env->GetIntField(settings, env->GetFieldID(clazz, "mScanType", "I")));
+    bool isDiseqcRxMessage = static_cast<bool>(env->GetBooleanField(
+            settings, env->GetFieldID(clazz, "mIsDiseqcRxMessage", "B")));
+
+    FrontendDvbsSettingsExt1_1 dvbsExt1_1 {
+        .scanType = scanType,
+        .isDiseqcRxMessage = isDiseqcRxMessage,
+    };
+    settingsExt1_1.settingExt.dvbs(dvbsExt1_1);
+}
+
 static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& settings) {
     FrontendSettings frontendSettings;
     uint32_t freq = getFrontendSettingsFreq(env, settings);
@@ -2291,6 +2472,25 @@
     return frontendSettings;
 }
 
+static void getDvbtFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings,
+        FrontendSettingsExt1_1& settingsExt1_1) {
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendSettings");
+
+    FrontendDvbtSettingsExt1_1 dvbtExt1_1;
+    int transmissionMode =
+            env->GetIntField(settings, env->GetFieldID(clazz, "mTransmissionMode", "I"));
+    dvbtExt1_1.transmissionMode = static_cast<
+            ::android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode>(
+                    transmissionMode);
+
+    int constellation =
+            env->GetIntField(settings, env->GetFieldID(clazz, "mConstellation", "I"));
+    dvbtExt1_1.constellation = static_cast<
+            ::android::hardware::tv::tuner::V1_1::FrontendDvbtConstellation>(constellation);
+
+    settingsExt1_1.settingExt.dvbt(dvbtExt1_1);
+}
+
 static FrontendSettings getIsdbsFrontendSettings(JNIEnv *env, const jobject& settings) {
     FrontendSettings frontendSettings;
     uint32_t freq = getFrontendSettingsFreq(env, settings);
@@ -2431,6 +2631,54 @@
     }
 }
 
+static FrontendSettingsExt1_1 getFrontendSettingsExt1_1(JNIEnv *env, int type, jobject settings) {
+    ALOGD("getFrontendSettingsExt1_1 %d", type);
+
+    FrontendSettingsExt1_1 settingsExt1_1 {
+        .endFrequency = static_cast<uint32_t>(Constant::INVALID_FRONTEND_SETTING_FREQUENCY),
+        .inversion = FrontendSpectralInversion::UNDEFINED,
+    };
+    settingsExt1_1.settingExt.noinit();
+    FrontendType feType = static_cast<FrontendType>(type);
+    switch(feType) {
+        case FrontendType::DVBS:
+            getDvbsFrontendSettingsExt1_1(env, settings, settingsExt1_1);
+            break;
+        case FrontendType::DVBT:
+            getDvbtFrontendSettingsExt1_1(env, settings, settingsExt1_1);
+            break;
+        case FrontendType::ANALOG:
+            getAnalogFrontendSettingsExt1_1(env, settings, settingsExt1_1);
+            break;
+        case FrontendType::ATSC3:
+            break;
+        case FrontendType::ATSC:
+            break;
+        case FrontendType::DVBC:
+            getDvbcFrontendSettingsExt1_1(env, settings, settingsExt1_1);
+            break;
+        case FrontendType::ISDBS:
+            break;
+        case FrontendType::ISDBS3:
+            break;
+        case FrontendType::ISDBT:
+            break;
+        default:
+            // should never happen because a type is associated with a subclass of
+            // FrontendSettings and not set by users
+            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                "Unsupported frontend type %d", type);
+            return FrontendSettingsExt1_1();
+    }
+
+    uint32_t endFreq = getFrontendSettingsEndFreq(env, settings);
+    FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings);
+    settingsExt1_1.endFrequency = endFreq;
+    settingsExt1_1.inversion = inversion;
+
+    return settingsExt1_1;
+}
+
 static sp<Filter> getFilter(JNIEnv *env, jobject filter) {
     return (Filter *)env->GetLongField(filter, gFields.filterContext);
 }
@@ -2572,7 +2820,9 @@
 
 static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
     sp<JTuner> tuner = getTuner(env, thiz);
-    return tuner->tune(getFrontendSettings(env, type, settings));
+    FrontendSettings setting = getFrontendSettings(env, type, settings);
+    FrontendSettingsExt1_1 settingExt = getFrontendSettingsExt1_1(env, type, settings);
+    return tuner->tune(setting, settingExt);
 }
 
 static int android_media_tv_Tuner_stop_tune(JNIEnv *env, jobject thiz) {
@@ -2583,8 +2833,9 @@
 static int android_media_tv_Tuner_scan(
         JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) {
     sp<JTuner> tuner = getTuner(env, thiz);
-    return tuner->scan(getFrontendSettings(
-            env, settingsType, settings), static_cast<FrontendScanType>(scanType));
+    FrontendSettings setting = getFrontendSettings(env, settingsType, settings);
+    FrontendSettingsExt1_1 settingExt = getFrontendSettingsExt1_1(env, settingsType, settings);
+    return tuner->scan(setting, static_cast<FrontendScanType>(scanType), settingExt);
 }
 
 static int android_media_tv_Tuner_stop_scan(JNIEnv *env, jobject thiz) {
@@ -2629,11 +2880,21 @@
     return tuner->connectCiCam(id);
 }
 
+static int android_media_tv_Tuner_link_cicam(JNIEnv *env, jobject thiz, jint id) {
+    sp<JTuner> tuner = getTuner(env, thiz);
+    return tuner->linkCiCam(id);
+}
+
 static int android_media_tv_Tuner_disconnect_cicam(JNIEnv *env, jobject thiz) {
     sp<JTuner> tuner = getTuner(env, thiz);
     return tuner->disconnectCiCam();
 }
 
+static int android_media_tv_Tuner_unlink_cicam(JNIEnv *env, jobject thiz, jint id) {
+    sp<JTuner> tuner = getTuner(env, thiz);
+    return tuner->unlinkCiCam(id);
+}
+
 static jobject android_media_tv_Tuner_get_frontend_info(JNIEnv *env, jobject thiz, jint id) {
     sp<JTuner> tuner = getTuner(env, thiz);
     return tuner->getFrontendInfo(id);
@@ -3041,6 +3302,29 @@
     return filterSettings;
 }
 
+static Result configureIpFilterContextId(
+        JNIEnv *env, sp<IFilter> iFilterSp, jobject ipFilterConfigObj) {
+    jclass clazz = env->FindClass(
+            "android/media/tv/tuner/filter/IpFilterConfiguration");
+    uint32_t cid = env->GetIntField(ipFilterConfigObj, env->GetFieldID(
+            clazz, "mIpFilterContextId", "I"));
+    Result res = Result::SUCCESS;
+    if (cid != static_cast<uint32_t>(Constant::INVALID_IP_FILTER_CONTEXT_ID)) {
+        sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
+        iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
+
+        if (iFilterSp_1_1 != NULL) {
+            res = iFilterSp_1_1->configureIpCid(cid);
+            if (res != Result::SUCCESS) {
+                return res;
+            }
+        } else {
+            ALOGW("configureIpCid is not supported with the current HAL implementation.");
+        }
+    }
+    return res;
+}
+
 static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyteArray buffer,
         jlong offset, jlong size) {
     ALOGD("copyData, size=%ld, offset=%ld", (long) size, (long) offset);
@@ -3084,6 +3368,13 @@
         return (jint) res;
     }
 
+    if (static_cast<DemuxFilterMainType>(type) == DemuxFilterMainType::IP) {
+        res = configureIpFilterContextId(env, iFilterSp, settings);
+        if (res != Result::SUCCESS) {
+            return (jint) res;
+        }
+    }
+
     MQDescriptorSync<uint8_t> filterMQDesc;
     Result getQueueDescResult = Result::UNKNOWN_ERROR;
     if (filterSp->mFilterMQ == NULL) {
@@ -3786,6 +4077,10 @@
     { "nativeGetAvSyncTime", "(I)Ljava/lang/Long;",
             (void *)android_media_tv_Tuner_get_av_sync_time },
     { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam },
+    { "nativeLinkCiCam", "(I)I",
+            (void *)android_media_tv_Tuner_link_cicam },
+    { "nativeUnlinkCiCam", "(I)I",
+            (void *)android_media_tv_Tuner_unlink_cicam },
     { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam },
     { "nativeGetFrontendInfo", "(I)Landroid/media/tv/tuner/frontend/FrontendInfo;",
             (void *)android_media_tv_Tuner_get_frontend_info },
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index d7dc600..d70a5ff 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -19,6 +19,7 @@
 
 #include <android/hardware/tv/tuner/1.1/IFilter.h>
 #include <android/hardware/tv/tuner/1.1/IFilterCallback.h>
+#include <android/hardware/tv/tuner/1.1/IFrontend.h>
 #include <android/hardware/tv/tuner/1.1/ITuner.h>
 #include <android/hardware/tv/tuner/1.1/types.h>
 
@@ -54,6 +55,7 @@
 using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
 using ::android::hardware::tv::tuner::V1_0::FrontendScanType;
 using ::android::hardware::tv::tuner::V1_0::FrontendSettings;
+using ::android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1;
 using ::android::hardware::tv::tuner::V1_0::IDemux;
 using ::android::hardware::tv::tuner::V1_0::IDescrambler;
 using ::android::hardware::tv::tuner::V1_0::IDvr;
@@ -117,28 +119,6 @@
     int mFd;
 };
 
-struct MediaEvent : public RefBase {
-    MediaEvent(sp<IFilter> iFilter, hidl_handle avHandle, uint64_t dataId,
-        uint64_t dataLength, jobject obj);
-    ~MediaEvent();
-    jobject getLinearBlock();
-    uint64_t getAudioHandle();
-    void finalize();
-
-    sp<IFilter> mIFilter;
-    native_handle_t* mAvHandle;
-    uint64_t mDataId;
-    uint64_t mDataLength;
-    uint8_t* mBuffer;
-    android::Mutex mLock;
-    int mDataIdRefCnt;
-    int mAvHandleRefCnt;
-    jweak mMediaEventObj;
-    jweak mLinearBlockObj;
-    C2HandleIon* mIonHandle;
-    std::weak_ptr<C2Buffer> mC2Buffer;
-};
-
 struct Filter : public RefBase {
     Filter(sp<IFilter> sp, jobject obj);
     ~Filter();
@@ -148,6 +128,31 @@
     std::unique_ptr<MQ> mFilterMQ;
     EventFlag* mFilterMQEventFlag;
     jweak mFilterObj;
+    native_handle_t* mAvSharedHandle;
+    uint64_t mAvSharedMemSize;
+    bool mIsMediaFilter;
+};
+
+struct MediaEvent : public RefBase {
+    MediaEvent(sp<Filter> filter, hidl_handle avHandle, uint64_t dataId,
+        uint64_t dataSize, jobject obj);
+    ~MediaEvent();
+    jobject getLinearBlock();
+    uint64_t getAudioHandle();
+    void finalize();
+
+    sp<Filter> mFilter;
+    native_handle_t* mAvHandle;
+    uint64_t mDataId;
+    uint64_t mDataSize;
+    uint8_t* mBuffer;
+    android::Mutex mLock;
+    int mDataIdRefCnt;
+    int mAvHandleRefCnt;
+    jweak mMediaEventObj;
+    jweak mLinearBlockObj;
+    C2HandleIon* mIonHandle;
+    std::weak_ptr<C2Buffer> mC2Buffer;
 };
 
 struct FilterCallback : public IFilterCallback {
@@ -159,8 +164,7 @@
 
     void setFilter(const sp<Filter> filter);
 private:
-    jweak mFilter;
-    sp<IFilter> mIFilter;
+    sp<Filter> mFilter;
     jobjectArray getSectionEvent(
             jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
     jobjectArray getMediaEvent(
@@ -207,14 +211,17 @@
     jobject getAvSyncHwId(sp<Filter> filter);
     jobject getAvSyncTime(jint id);
     int connectCiCam(jint id);
+    int linkCiCam(jint id);
     int disconnectCiCam();
+    int unlinkCiCam(jint id);
     jobject getFrontendIds();
     jobject openFrontendById(int id);
     jint closeFrontendById(int id);
     jobject getFrontendInfo(int id);
-    int tune(const FrontendSettings& settings);
+    int tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
     int stopTune();
-    int scan(const FrontendSettings& settings, FrontendScanType scanType);
+    int scan(const FrontendSettings& settings, FrontendScanType scanType,
+            const FrontendSettingsExt1_1& settingsExt1_1);
     int stopScan();
     int setLnb(int id);
     int setLna(bool enable);
@@ -245,6 +252,7 @@
     static int mTunerVersion;
     hidl_vec<FrontendId> mFeIds;
     sp<IFrontend> mFe;
+    sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFe_1_1;
     int mFeId;
     hidl_vec<LnbId> mLnbIds;
     sp<ILnb> mLnb;
diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp
index 23035b6..ac4c16a 100644
--- a/native/graphics/jni/imagedecoder.cpp
+++ b/native/graphics/jni/imagedecoder.cpp
@@ -353,3 +353,18 @@
     ImageDecoder* imageDecoder = toDecoder(decoder);
     return imageDecoder->mCodec->codec()->getFrameCount() > 1;
 }
+
+int32_t AImageDecoder_getRepeatCount(AImageDecoder* decoder) {
+    if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
+
+    ImageDecoder* imageDecoder = toDecoder(decoder);
+    const int count = imageDecoder->mCodec->codec()->getRepetitionCount();
+
+    // Skia should not report anything out of range, but defensively treat
+    // negative and too big as INFINITE.
+    if (count == SkCodec::kRepetitionCountInfinite || count < 0
+        || count > std::numeric_limits<int32_t>::max()) {
+        return ANDROID_IMAGE_DECODER_INFINITE;
+    }
+    return count;
+}
diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt
index af2c455..a184ab9 100644
--- a/native/graphics/jni/libjnigraphics.map.txt
+++ b/native/graphics/jni/libjnigraphics.map.txt
@@ -14,6 +14,7 @@
     AImageDecoder_computeSampledSize; # introduced=30
     AImageDecoder_setCrop; # introduced=30
     AImageDecoder_isAnimated; # introduced=31
+    AImageDecoder_getRepeatCount; # introduced=31
     AImageDecoderHeaderInfo_getWidth; # introduced=30
     AImageDecoderHeaderInfo_getHeight; # introduced=30
     AImageDecoderHeaderInfo_getMimeType; # introduced=30
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 8596f87..e3718c9 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -2889,6 +2889,7 @@
     field public static final int GESTURE_2_FINGER_DOUBLE_TAP = 20; // 0x14
     field public static final int GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD = 40; // 0x28
     field public static final int GESTURE_2_FINGER_SINGLE_TAP = 19; // 0x13
+    field public static final int GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD = 43; // 0x2b
     field public static final int GESTURE_2_FINGER_SWIPE_DOWN = 26; // 0x1a
     field public static final int GESTURE_2_FINGER_SWIPE_LEFT = 27; // 0x1b
     field public static final int GESTURE_2_FINGER_SWIPE_RIGHT = 28; // 0x1c
@@ -2897,11 +2898,13 @@
     field public static final int GESTURE_3_FINGER_DOUBLE_TAP = 23; // 0x17
     field public static final int GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD = 41; // 0x29
     field public static final int GESTURE_3_FINGER_SINGLE_TAP = 22; // 0x16
+    field public static final int GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD = 44; // 0x2c
     field public static final int GESTURE_3_FINGER_SWIPE_DOWN = 30; // 0x1e
     field public static final int GESTURE_3_FINGER_SWIPE_LEFT = 31; // 0x1f
     field public static final int GESTURE_3_FINGER_SWIPE_RIGHT = 32; // 0x20
     field public static final int GESTURE_3_FINGER_SWIPE_UP = 29; // 0x1d
     field public static final int GESTURE_3_FINGER_TRIPLE_TAP = 24; // 0x18
+    field public static final int GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD = 45; // 0x2d
     field public static final int GESTURE_4_FINGER_DOUBLE_TAP = 38; // 0x26
     field public static final int GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD = 42; // 0x2a
     field public static final int GESTURE_4_FINGER_SINGLE_TAP = 37; // 0x25
@@ -10664,12 +10667,15 @@
     field public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
     field public static final String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
+    field public static final String ACTION_PACKAGE_FULLY_LOADED = "android.intent.action.PACKAGE_FULLY_LOADED";
     field public static final String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field @Deprecated public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
     field public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
     field public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
     field public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
     field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
+    field public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
+    field public static final String ACTION_PACKAGE_UNSTARTABLE = "android.intent.action.PACKAGE_UNSTARTABLE";
     field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
     field public static final String ACTION_PASTE = "android.intent.action.PASTE";
     field public static final String ACTION_PICK = "android.intent.action.PICK";
@@ -10834,6 +10840,7 @@
     field public static final String EXTRA_TIMEZONE = "time-zone";
     field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
     field public static final String EXTRA_UID = "android.intent.extra.UID";
+    field public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
     field public static final String EXTRA_USER = "android.intent.extra.USER";
     field public static final int FILL_IN_ACTION = 1; // 0x1
     field public static final int FILL_IN_CATEGORIES = 4; // 0x4
@@ -12293,6 +12300,9 @@
     field public static final int SYNCHRONOUS = 2; // 0x2
     field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL;
     field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE;
+    field public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1; // 0x1
+    field public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2; // 0x2
+    field public static final int UNSTARTABLE_REASON_UNKNOWN = 0; // 0x0
     field public static final int VERIFICATION_ALLOW = 1; // 0x1
     field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
     field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
@@ -24071,9 +24081,13 @@
     method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
     method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
     method @IntRange(from=0) public long getMinUpdateIntervalMillis();
+    method public int getQuality();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
     field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
+    field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
+    field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
+    field public static final int QUALITY_LOW_POWER = 104; // 0x68
   }
 
   public static final class LocationRequest.Builder {
@@ -24086,6 +24100,7 @@
     method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
     method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
     method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
+    method @NonNull public android.location.LocationRequest.Builder setQuality(int);
   }
 
   public interface OnNmeaMessageListener {
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index b19ce48..3c1d19f 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -1,10 +1,20 @@
 // Signature format: 2.0
 package android.app {
 
+  public class ActivityManager {
+    method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
+    method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
+  }
+
   public class AppOpsManager {
     field public static final String OPSTR_NO_ISOLATED_STORAGE = "android:no_isolated_storage";
   }
 
+  public abstract class HomeVisibilityListener {
+    ctor public HomeVisibilityListener();
+    method public abstract void onHomeVisibilityChanged(boolean);
+  }
+
   public class NotificationManager {
     method public boolean hasEnabledNotificationListener(@NonNull String, @NonNull android.os.UserHandle);
     field public static final String ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED = "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED";
@@ -123,6 +133,18 @@
 
 }
 
+package android.telephony {
+
+  public abstract class CellSignalStrength {
+    method public static int getNumSignalStrengthLevels();
+  }
+
+  public class TelephonyManager {
+    method @NonNull public static int[] getAllNetworkTypes();
+  }
+
+}
+
 package android.util {
 
   public class AtomicFile {
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index 75e038be..50062bf 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -122,6 +122,7 @@
     field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
     field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
     field public static final String MANAGE_MUSIC_RECOGNITION = "android.permission.MANAGE_MUSIC_RECOGNITION";
+    field public static final String MANAGE_NOTIFICATION_LISTENERS = "android.permission.MANAGE_NOTIFICATION_LISTENERS";
     field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS";
     field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
     field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
@@ -674,8 +675,10 @@
   public class NotificationManager {
     method @NonNull public java.util.List<java.lang.String> getAllowedAssistantAdjustments();
     method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
+    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners();
     method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
     method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean);
     field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL = "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL";
     field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL = "android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL";
     field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL = "android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL";
@@ -4111,7 +4114,6 @@
     method @Deprecated public long getInterval();
     method @Deprecated public int getNumUpdates();
     method @Deprecated @NonNull public String getProvider();
-    method public int getQuality();
     method @Deprecated public float getSmallestDisplacement();
     method @NonNull public android.os.WorkSource getWorkSource();
     method public boolean isHiddenFromAppOps();
@@ -4130,11 +4132,11 @@
     method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
     method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
     method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
-    field public static final int ACCURACY_BLOCK = 102; // 0x66
-    field public static final int ACCURACY_CITY = 104; // 0x68
-    field public static final int ACCURACY_FINE = 100; // 0x64
-    field public static final int POWER_HIGH = 203; // 0xcb
-    field public static final int POWER_LOW = 201; // 0xc9
+    field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
+    field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
+    field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
+    field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
+    field @Deprecated public static final int POWER_LOW = 201; // 0xc9
     field @Deprecated public static final int POWER_NONE = 200; // 0xc8
   }
 
@@ -4142,7 +4144,6 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
     method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
     method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
-    method @NonNull public android.location.LocationRequest.Builder setQuality(int);
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
   }
 
@@ -4709,6 +4710,22 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.DvbDeviceInfo> CREATOR;
   }
 
+  public final class TunedInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getAppTag();
+    method public int getAppType();
+    method @Nullable public android.net.Uri getChannelUri();
+    method @NonNull public String getInputId();
+    method public boolean isForeground();
+    method public boolean isRecordingSession();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int APP_TAG_SELF = 0; // 0x0
+    field public static final int APP_TYPE_NON_SYSTEM = 3; // 0x3
+    field public static final int APP_TYPE_SELF = 1; // 0x1
+    field public static final int APP_TYPE_SYSTEM = 2; // 0x2
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.TunedInfo> CREATOR;
+  }
+
   public final class TvContentRatingSystemInfo implements android.os.Parcelable {
     method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo);
     method public int describeContents();
@@ -4824,6 +4841,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating);
     method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig);
     method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String);
+    method @NonNull @RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS") public java.util.List<android.media.tv.TunedInfo> getCurrentTunedInfos();
     method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList();
     method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList();
     method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList();
@@ -4849,6 +4867,10 @@
     method public abstract void onStreamConfigChanged(android.media.tv.TvStreamConfig[]);
   }
 
+  public abstract static class TvInputManager.TvInputCallback {
+    method public void onCurrentTunedInfosUpdated(@NonNull java.util.List<android.media.tv.TunedInfo>);
+  }
+
   public abstract class TvInputService extends android.app.Service {
     method @Nullable public android.media.tv.TvInputInfo onHardwareAdded(android.media.tv.TvInputHardwareInfo);
     method @Nullable public String onHardwareRemoved(android.media.tv.TvInputHardwareInfo);
@@ -4976,6 +4998,7 @@
     method @Nullable public android.media.tv.tuner.DemuxCapabilities getDemuxCapabilities();
     method @Nullable public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
     method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
+    method public int linkFrontendToCiCam(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler();
     method @Nullable public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
     method @Nullable public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnRecordStatusChangedListener);
@@ -4989,10 +5012,13 @@
     method public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener);
     method public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner);
     method public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings);
+    method public int unlinkFrontendToCiCam(int);
     method public void updateResourcePriority(int, int);
     field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff
     field public static final int INVALID_FILTER_ID = -1; // 0xffffffff
     field public static final long INVALID_FILTER_ID_64BIT = -1L; // 0xffffffffffffffffL
+    field public static final int INVALID_FRONTEND_SETTING_FREQUENCY = -1; // 0xffffffff
+    field public static final int INVALID_LTS_ID = -1; // 0xffffffff
     field public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1; // 0xffffffff
     field public static final int INVALID_STREAM_ID = 65535; // 0xffff
     field public static final long INVALID_TIMESTAMP = -1L; // 0xffffffffffffffffL
@@ -5205,16 +5231,19 @@
     method @NonNull public static android.media.tv.tuner.filter.IpFilterConfiguration.Builder builder();
     method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress();
     method public int getDstPort();
+    method public int getIpFilterContextId();
     method @NonNull @Size(min=4, max=16) public byte[] getSrcIpAddress();
     method public int getSrcPort();
     method public int getType();
     method public boolean isPassthrough();
+    field public static final int INVALID_IP_FILTER_CONTEXT_ID = -1; // 0xffffffff
   }
 
   public static final class IpFilterConfiguration.Builder {
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration build();
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstIpAddress(@NonNull byte[]);
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstPort(int);
+    method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setIpFilterContextId(int);
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setPassthrough(boolean);
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSettings(@Nullable android.media.tv.tuner.filter.Settings);
     method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSrcIpAddress(@NonNull byte[]);
@@ -5434,9 +5463,13 @@
 
   public class AnalogFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
     method @NonNull public static android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder builder();
+    method public int getAftFlag();
     method public int getSifStandard();
     method public int getSignalType();
     method public int getType();
+    field public static final int AFT_FLAG_FALSE = 2; // 0x2
+    field public static final int AFT_FLAG_TRUE = 1; // 0x1
+    field public static final int AFT_FLAG_UNDEFINED = 0; // 0x0
     field public static final int SIF_AUTO = 1; // 0x1
     field public static final int SIF_BG = 2; // 0x2
     field public static final int SIF_BG_A2 = 4; // 0x4
@@ -5469,6 +5502,7 @@
 
   public static class AnalogFrontendSettings.Builder {
     method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings build();
+    method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setAftFlag(int);
     method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setFrequency(int);
     method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSifStandard(int);
     method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSignalType(int);
@@ -5598,6 +5632,7 @@
     method public int getOuterFec();
     method public int getSpectralInversion();
     method public int getSymbolRate();
+    method public int getTimeInterleaveMode();
     method public int getType();
     field public static final int ANNEX_A = 1; // 0x1
     field public static final int ANNEX_B = 2; // 0x2
@@ -5616,6 +5651,17 @@
     field public static final int SPECTRAL_INVERSION_INVERTED = 2; // 0x2
     field public static final int SPECTRAL_INVERSION_NORMAL = 1; // 0x1
     field public static final int SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0
+    field public static final int TIME_INTERLEAVE_MODE_128_1_0 = 2; // 0x2
+    field public static final int TIME_INTERLEAVE_MODE_128_1_1 = 4; // 0x4
+    field public static final int TIME_INTERLEAVE_MODE_128_2 = 128; // 0x80
+    field public static final int TIME_INTERLEAVE_MODE_128_3 = 256; // 0x100
+    field public static final int TIME_INTERLEAVE_MODE_128_4 = 512; // 0x200
+    field public static final int TIME_INTERLEAVE_MODE_16_8 = 32; // 0x20
+    field public static final int TIME_INTERLEAVE_MODE_32_4 = 16; // 0x10
+    field public static final int TIME_INTERLEAVE_MODE_64_2 = 8; // 0x8
+    field public static final int TIME_INTERLEAVE_MODE_8_16 = 64; // 0x40
+    field public static final int TIME_INTERLEAVE_MODE_AUTO = 1; // 0x1
+    field public static final int TIME_INTERLEAVE_MODE_UNDEFINED = 0; // 0x0
   }
 
   public static class DvbcFrontendSettings.Builder {
@@ -5627,6 +5673,7 @@
     method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setOuterFec(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSpectralInversion(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSymbolRate(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setTimeInterleaveMode(int);
   }
 
   public class DvbsCodeRate {
@@ -5658,6 +5705,7 @@
     method public int getModulation();
     method public int getPilot();
     method public int getRolloff();
+    method public int getScanType();
     method public int getStandard();
     method public int getSymbolRate();
     method public int getType();
@@ -5688,6 +5736,11 @@
     field public static final int ROLLOFF_0_35 = 1; // 0x1
     field public static final int ROLLOFF_0_5 = 6; // 0x6
     field public static final int ROLLOFF_UNDEFINED = 0; // 0x0
+    field public static final int SCAN_TYPE_DIRECT = 1; // 0x1
+    field public static final int SCAN_TYPE_DISEQC = 2; // 0x2
+    field public static final int SCAN_TYPE_JESS = 4; // 0x4
+    field public static final int SCAN_TYPE_UNDEFINED = 0; // 0x0
+    field public static final int SCAN_TYPE_UNICABLE = 3; // 0x3
     field public static final int STANDARD_AUTO = 1; // 0x1
     field public static final int STANDARD_S = 2; // 0x2
     field public static final int STANDARD_S2 = 4; // 0x4
@@ -5705,6 +5758,7 @@
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setPilot(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setRolloff(int);
+    method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setScanType(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setStandard(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setSymbolRate(int);
     method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setVcmMode(int);
@@ -5757,10 +5811,14 @@
     field public static final int CODERATE_AUTO = 1; // 0x1
     field public static final int CODERATE_UNDEFINED = 0; // 0x0
     field public static final int CONSTELLATION_16QAM = 4; // 0x4
+    field public static final int CONSTELLATION_16QAM_R = 64; // 0x40
     field public static final int CONSTELLATION_256QAM = 16; // 0x10
+    field public static final int CONSTELLATION_256QAM_R = 256; // 0x100
     field public static final int CONSTELLATION_64QAM = 8; // 0x8
+    field public static final int CONSTELLATION_64QAM_R = 128; // 0x80
     field public static final int CONSTELLATION_AUTO = 1; // 0x1
     field public static final int CONSTELLATION_QPSK = 2; // 0x2
+    field public static final int CONSTELLATION_QPSK_R = 32; // 0x20
     field public static final int CONSTELLATION_UNDEFINED = 0; // 0x0
     field public static final int GUARD_INTERVAL_19_128 = 64; // 0x40
     field public static final int GUARD_INTERVAL_19_256 = 128; // 0x80
@@ -5794,6 +5852,9 @@
     field public static final int TRANSMISSION_MODE_4K = 8; // 0x8
     field public static final int TRANSMISSION_MODE_8K = 4; // 0x4
     field public static final int TRANSMISSION_MODE_AUTO = 1; // 0x1
+    field public static final int TRANSMISSION_MODE_EXTENDED_16K = 256; // 0x100
+    field public static final int TRANSMISSION_MODE_EXTENDED_32K = 512; // 0x200
+    field public static final int TRANSMISSION_MODE_EXTENDED_8K = 128; // 0x80
     field public static final int TRANSMISSION_MODE_UNDEFINED = 0; // 0x0
   }
 
@@ -5831,8 +5892,12 @@
   }
 
   public abstract class FrontendSettings {
+    method public int getEndFrequency();
     method public int getFrequency();
+    method public int getFrontendSpectralInversion();
     method public abstract int getType();
+    method @IntRange(from=1) public void setEndFrequency(int);
+    method public void setSpectralInversion(int);
     field public static final long FEC_11_15 = 4194304L; // 0x400000L
     field public static final long FEC_11_20 = 8388608L; // 0x800000L
     field public static final long FEC_11_45 = 16777216L; // 0x1000000L
@@ -5870,6 +5935,9 @@
     field public static final long FEC_9_20 = 2097152L; // 0x200000L
     field public static final long FEC_AUTO = 1L; // 0x1L
     field public static final long FEC_UNDEFINED = 0L; // 0x0L
+    field public static final int FRONTEND_SPECTRAL_INVERSION_INVERTED = 2; // 0x2
+    field public static final int FRONTEND_SPECTRAL_INVERSION_NORMAL = 1; // 0x1
+    field public static final int FRONTEND_SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0
     field public static final int TYPE_ANALOG = 1; // 0x1
     field public static final int TYPE_ATSC = 2; // 0x2
     field public static final int TYPE_ATSC3 = 3; // 0x3
@@ -9899,6 +9967,25 @@
     field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
   }
 
+  public final class ModemActivityInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo);
+    method public long getIdleTimeMillis();
+    method public static int getNumTxPowerLevels();
+    method public long getReceiveTimeMillis();
+    method public long getSleepTimeMillis();
+    method public long getTimestampMillis();
+    method public long getTransmitDurationMillisAtPowerLevel(int);
+    method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
+    field public static final int TX_POWER_LEVEL_0 = 0; // 0x0
+    field public static final int TX_POWER_LEVEL_1 = 1; // 0x1
+    field public static final int TX_POWER_LEVEL_2 = 2; // 0x2
+    field public static final int TX_POWER_LEVEL_3 = 3; // 0x3
+    field public static final int TX_POWER_LEVEL_4 = 4; // 0x4
+  }
+
   public final class NetworkRegistrationInfo implements android.os.Parcelable {
     method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
     method public int getRegistrationState();
diff --git a/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java b/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java
index 900e68d..6827d6e 100644
--- a/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java
+++ b/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java
@@ -19,6 +19,9 @@
 import static android.content.Intent.ACTION_USER_SWITCHED;
 import static android.location.LocationManager.GPS_PROVIDER;
 import static android.location.LocationManager.NETWORK_PROVIDER;
+import static android.location.LocationRequest.QUALITY_LOW_POWER;
+
+import static com.android.location.provider.ProviderRequestUnbundled.INTERVAL_DISABLED;
 
 import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
@@ -35,7 +38,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.location.ProviderRequest;
 import com.android.location.provider.LocationProviderBase;
-import com.android.location.provider.LocationRequestUnbundled;
 import com.android.location.provider.ProviderPropertiesUnbundled;
 import com.android.location.provider.ProviderRequestUnbundled;
 
@@ -147,8 +149,8 @@
 
         mRequest = new ProviderRequestUnbundled(ProviderRequest.EMPTY_REQUEST);
         mWorkSource = new WorkSource();
-        mGpsInterval = Long.MAX_VALUE;
-        mNetworkInterval = Long.MAX_VALUE;
+        mGpsInterval = INTERVAL_DISABLED;
+        mNetworkInterval = INTERVAL_DISABLED;
     }
 
     void start() {
@@ -175,30 +177,9 @@
 
     @GuardedBy("mLock")
     private void updateRequirementsLocked() {
-        long gpsInterval = Long.MAX_VALUE;
-        long networkInterval = Long.MAX_VALUE;
-        if (mRequest.getReportLocation()) {
-            for (LocationRequestUnbundled request : mRequest.getLocationRequests()) {
-                switch (request.getQuality()) {
-                    case LocationRequestUnbundled.ACCURACY_FINE:
-                    case LocationRequestUnbundled.ACCURACY_BLOCK:
-                    case LocationRequestUnbundled.POWER_HIGH:
-                        if (request.getInterval() < gpsInterval) {
-                            gpsInterval = request.getInterval();
-                        }
-                        if (request.getInterval() < networkInterval) {
-                            networkInterval = request.getInterval();
-                        }
-                        break;
-                    case LocationRequestUnbundled.ACCURACY_CITY:
-                    case LocationRequestUnbundled.POWER_LOW:
-                        if (request.getInterval() < networkInterval) {
-                            networkInterval = request.getInterval();
-                        }
-                        break;
-                }
-            }
-        }
+        long gpsInterval = mRequest.getQuality() < QUALITY_LOW_POWER ? mRequest.getInterval()
+                : INTERVAL_DISABLED;
+        long networkInterval = mRequest.getInterval();
 
         if (gpsInterval != mGpsInterval) {
             resetProviderRequestLocked(GPS_PROVIDER, mGpsInterval, gpsInterval, mGpsListener);
@@ -214,11 +195,12 @@
     @GuardedBy("mLock")
     private void resetProviderRequestLocked(String provider, long oldInterval, long newInterval,
             LocationListener listener) {
-        if (oldInterval != Long.MAX_VALUE) {
+        if (oldInterval != INTERVAL_DISABLED && newInterval == INTERVAL_DISABLED) {
             mLocationManager.removeUpdates(listener);
         }
-        if (newInterval != Long.MAX_VALUE) {
+        if (newInterval != INTERVAL_DISABLED) {
             LocationRequest request = new LocationRequest.Builder(newInterval)
+                    .setQuality(mRequest.getQuality())
                     .setLocationSettingsIgnored(mRequest.isLocationSettingsIgnored())
                     .setWorkSource(mWorkSource)
                     .build();
@@ -254,10 +236,10 @@
     void dump(PrintWriter writer) {
         synchronized (mLock) {
             writer.println("request: " + mRequest);
-            if (mGpsInterval != Long.MAX_VALUE) {
+            if (mGpsInterval != INTERVAL_DISABLED) {
                 writer.println("  gps interval: " + mGpsInterval);
             }
-            if (mNetworkInterval != Long.MAX_VALUE) {
+            if (mNetworkInterval != INTERVAL_DISABLED) {
                 writer.println("  network interval: " + mNetworkInterval);
             }
             if (mGpsLocation != null) {
diff --git a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
index d3aa977..61349d9 100644
--- a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
+++ b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
@@ -48,7 +48,6 @@
 import java.io.ByteArrayOutputStream;
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.util.Collections;
 import java.util.Random;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -60,7 +59,6 @@
 
     private static final long TIMEOUT_MS = 5000;
 
-    private Context mContext;
     private Random mRandom;
     private LocationManager mLocationManager;
 
@@ -72,15 +70,15 @@
         long seed = System.currentTimeMillis();
         Log.i(TAG, "location seed: " + seed);
 
-        mContext = InstrumentationRegistry.getTargetContext();
+        Context context = InstrumentationRegistry.getTargetContext();
         mRandom = new Random(seed);
-        mLocationManager = mContext.getSystemService(LocationManager.class);
+        mLocationManager = context.getSystemService(LocationManager.class);
 
         setMockLocation(true);
 
         mManager = new LocationProviderManagerCapture();
         mProvider = ILocationProvider.Stub.asInterface(
-                new FusedLocationProvider(mContext).getBinder());
+                new FusedLocationProvider(context).getBinder());
         mProvider.setLocationProviderManager(mManager);
 
         mLocationManager.addTestProvider(NETWORK_PROVIDER,
@@ -118,12 +116,9 @@
 
     @Test
     public void testNetworkRequest() throws Exception {
-        LocationRequest request = new LocationRequest.Builder(1000).build();
-
         mProvider.setRequest(
                         new ProviderRequest.Builder()
                                 .setIntervalMillis(1000)
-                                .setLocationRequests(Collections.singletonList(request))
                                 .build(),
                 new WorkSource());
 
@@ -135,14 +130,10 @@
 
     @Test
     public void testGpsRequest() throws Exception {
-        LocationRequest request = new LocationRequest.Builder(1000)
-                .setQuality(LocationRequest.POWER_HIGH)
-                .build();
-
         mProvider.setRequest(
                 new ProviderRequest.Builder()
+                        .setQuality(LocationRequest.QUALITY_HIGH_ACCURACY)
                         .setIntervalMillis(1000)
-                        .setLocationRequests(Collections.singletonList(request))
                         .build(),
                 new WorkSource());
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index 8e140ca..83974af 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -254,7 +254,7 @@
         mLocationManager.requestLocationUpdates(
                 LocationManager.FUSED_PROVIDER,
                 new LocationRequest.Builder(LOCATION_UPDATE_MS)
-                        .setQuality(LocationRequest.POWER_LOW)
+                        .setQuality(LocationRequest.QUALITY_LOW_POWER)
                         .build(),
                 new HandlerExecutor(new Handler(Looper.getMainLooper())),
                 this);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index bba29db..5f018a0 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -335,6 +335,9 @@
     <!-- Permission required for CTS test - android.server.biometrics -->
     <uses-permission android:name="android.permission.TEST_BIOMETRIC" />
 
+    <!-- Permissions required for CTS test - NotificationManagerTest -->
+    <uses-permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 7cbbaf9..26b3ab8 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1217,7 +1217,7 @@
     <!-- Interior padding of the message bubble -->
     <dimen name="bubble_message_padding">4dp</dimen>
     <!-- Offset between bubbles in their stacked position. -->
-    <dimen name="bubble_stack_offset">5dp</dimen>
+    <dimen name="bubble_stack_offset">10dp</dimen>
     <!-- How far offscreen the bubble stack rests. Cuts off padding and part of icon bitmap. -->
     <dimen name="bubble_stack_offscreen">9dp</dimen>
     <!-- How far down the screen the stack starts. -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
index 86129e0..70021b6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
@@ -65,7 +65,7 @@
     public SyncRtSurfaceTransactionApplierCompat(View targetView) {
         mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
         mBarrierSurfaceControl = mTargetViewRootImpl != null
-            ? mTargetViewRootImpl.getRenderSurfaceControl() : null;
+            ? mTargetViewRootImpl.getSurfaceControl() : null;
 
         mApplyHandler = new Handler(new Callback() {
             @Override
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewRootImplCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewRootImplCompat.java
index 73783ae..4a28d56 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewRootImplCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewRootImplCompat.java
@@ -34,10 +34,6 @@
     }
 
     public SurfaceControl getRenderSurfaceControl() {
-        return mViewRoot == null ? null : mViewRoot.getRenderSurfaceControl();
-    }
-
-    public SurfaceControl getSurfaceControl() {
         return mViewRoot == null ? null : mViewRoot.getSurfaceControl();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
index 2365f12..47adffc 100644
--- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
@@ -111,9 +111,7 @@
         final String providerPkg = getIntent().getStringExtra("provider_pkg");
         if (providerPkg == null || mProviderPkg.equals(providerPkg)) return;
         final String callingPkg = getCallingPkg();
-        EventLog.writeEvent(0x534e4554, "159145361", getUid(callingPkg), String.format(
-                "pkg %s (disguised as %s) attempted to request permission to show %s slices in %s",
-                callingPkg, providerPkg, mProviderPkg, mCallingPkg));
+        EventLog.writeEvent(0x534e4554, "159145361", getUid(callingPkg));
     }
 
     @Nullable
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index c3474bb..340ca04 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -249,8 +249,8 @@
         if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
             updateDimensions();
             if (isWindowVisible()) {
-                mWm.removeView(mMirrorView);
-                createMirrorWindow();
+                deleteWindowMagnification();
+                enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN);
             }
         } else if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
             onRotate();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
index 69f7828..009114f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
@@ -18,6 +18,8 @@
 
 import static android.graphics.Paint.ANTI_ALIAS_FLAG;
 import static android.graphics.Paint.FILTER_BITMAP_FLAG;
+import static com.android.systemui.Interpolators.ALPHA_IN;
+import static com.android.systemui.Interpolators.ALPHA_OUT;
 
 import android.animation.ArgbEvaluator;
 import android.content.Context;
@@ -56,6 +58,11 @@
     /** Max width of the flyout, in terms of percent of the screen width. */
     private static final float FLYOUT_MAX_WIDTH_PERCENT = .6f;
 
+    /** Translation Y of fade animation. */
+    private static final float FLYOUT_FADE_Y = 40f;
+
+    private static final long FLYOUT_FADE_DURATION = 200L;
+
     private final int mFlyoutPadding;
     private final int mFlyoutSpaceFromBubble;
     private final int mPointerSize;
@@ -104,6 +111,9 @@
     /** The bounds of the flyout background, kept up to date as it transitions to the 'new' dot. */
     private final RectF mBgRect = new RectF();
 
+    /** The y position of the flyout, relative to the top of the screen. */
+    private float mFlyoutY = 0f;
+
     /**
      * Percent progress in the transition from flyout to 'new' dot. These two values are the inverse
      * of each other (if we're 40% transitioned to the dot, we're 60% flyout), but it makes the code
@@ -221,18 +231,33 @@
         mSenderText.setTextSize(TypedValue.COMPLEX_UNIT_PX, newFontSize);
     }
 
-    /** Configures the flyout, collapsed into to dot form. */
-    void setupFlyoutStartingAsDot(
-            Bubble.FlyoutMessage flyoutMessage,
-            PointF stackPos,
-            float parentWidth,
-            boolean arrowPointingLeft,
-            int dotColor,
-            @Nullable Runnable onLayoutComplete,
-            @Nullable Runnable onHide,
-            float[] dotCenter,
-            boolean hideDot) {
+    /*
+     * Fade animation for consecutive flyouts.
+     */
+    void animateUpdate(Bubble.FlyoutMessage flyoutMessage, float parentWidth, float stackY) {
+        fade(false /* in */);
+        updateFlyoutMessage(flyoutMessage, parentWidth);
+        // Wait for TextViews to layout with updated height.
+        post(() -> {
+            mFlyoutY = stackY + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
+            fade(true /* in */);
+        });
+    }
 
+    private void fade(boolean in) {
+        setAlpha(in ? 0f : 1f);
+        setTranslationY(in ? mFlyoutY : mFlyoutY + FLYOUT_FADE_Y);
+        animate()
+                .alpha(in ? 1f : 0f)
+                .setDuration(FLYOUT_FADE_DURATION)
+                .setInterpolator(in ? ALPHA_IN : ALPHA_OUT);
+        animate()
+                .translationY(in ? mFlyoutY : mFlyoutY - FLYOUT_FADE_Y)
+                .setDuration(FLYOUT_FADE_DURATION)
+                .setInterpolator(in ? ALPHA_IN : ALPHA_OUT);
+    }
+
+    private void updateFlyoutMessage(Bubble.FlyoutMessage flyoutMessage, float parentWidth) {
         final Drawable senderAvatar = flyoutMessage.senderAvatar;
         if (senderAvatar != null && flyoutMessage.isGroupChat) {
             mSenderAvatar.setVisibility(VISIBLE);
@@ -256,6 +281,27 @@
             mSenderText.setVisibility(GONE);
         }
 
+        // Set the flyout TextView's max width in terms of percent, and then subtract out the
+        // padding so that the entire flyout view will be the desired width (rather than the
+        // TextView being the desired width + extra padding).
+        mMessageText.setMaxWidth(maxTextViewWidth);
+        mMessageText.setText(flyoutMessage.message);
+    }
+
+    /** Configures the flyout, collapsed into dot form. */
+    void setupFlyoutStartingAsDot(
+            Bubble.FlyoutMessage flyoutMessage,
+            PointF stackPos,
+            float parentWidth,
+            boolean arrowPointingLeft,
+            int dotColor,
+            @Nullable Runnable onLayoutComplete,
+            @Nullable Runnable onHide,
+            float[] dotCenter,
+            boolean hideDot)  {
+
+        updateFlyoutMessage(flyoutMessage, parentWidth);
+
         mArrowPointingLeft = arrowPointingLeft;
         mDotColor = dotColor;
         mOnHide = onHide;
@@ -263,24 +309,12 @@
 
         setCollapsePercent(1f);
 
-        // Set the flyout TextView's max width in terms of percent, and then subtract out the
-        // padding so that the entire flyout view will be the desired width (rather than the
-        // TextView being the desired width + extra padding).
-        mMessageText.setMaxWidth(maxTextViewWidth);
-        mMessageText.setText(flyoutMessage.message);
-
-        // Wait for the TextView to lay out so we know its line count.
+        // Wait for TextViews to layout with updated height.
         post(() -> {
-            float restingTranslationY;
-            // Multi line flyouts get top-aligned to the bubble.
-            if (mMessageText.getLineCount() > 1) {
-                restingTranslationY = stackPos.y + mBubbleIconTopPadding;
-            } else {
-                // Single line flyouts are vertically centered with respect to the bubble.
-                restingTranslationY =
-                        stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
-            }
-            setTranslationY(restingTranslationY);
+            // Flyout is vertically centered with respect to the bubble.
+            mFlyoutY =
+                    stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
+            setTranslationY(mFlyoutY);
 
             // Calculate the translation required to position the flyout next to the bubble stack,
             // with the desired padding.
@@ -300,7 +334,7 @@
             final float dotPositionY = stackPos.y + mDotCenter[1] - adjustmentForScaleAway;
 
             final float distanceFromFlyoutLeftToDotCenterX = mRestingTranslationX - dotPositionX;
-            final float distanceFromLayoutTopToDotCenterY = restingTranslationY - dotPositionY;
+            final float distanceFromLayoutTopToDotCenterY = mFlyoutY - dotPositionY;
 
             mTranslationXWhenDot = -distanceFromFlyoutLeftToDotCenterX;
             mTranslationYWhenDot = -distanceFromLayoutTopToDotCenterY;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index e2674de..431719f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -2171,11 +2171,7 @@
         return getStatusBarHeight() + mBubbleSize + mBubblePaddingTop;
     }
 
-    /**
-     * Animates in the flyout for the given bubble, if available, and then hides it after some time.
-     */
-    @VisibleForTesting
-    void animateInFlyoutForBubble(Bubble bubble) {
+    private boolean shouldShowFlyout(Bubble bubble) {
         Bubble.FlyoutMessage flyoutMessage = bubble.getFlyoutMessage();
         final BadgedImageView bubbleView = bubble.getIconView();
         if (flyoutMessage == null
@@ -2187,11 +2183,22 @@
                 || mIsGestureInProgress
                 || mBubbleToExpandAfterFlyoutCollapse != null
                 || bubbleView == null) {
-            if (bubbleView != null) {
+            if (bubbleView != null && mFlyout.getVisibility() != VISIBLE) {
                 bubbleView.removeDotSuppressionFlag(BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
             }
             // Skip the message if none exists, we're expanded or animating expansion, or we're
             // about to expand a bubble from the previous tapped flyout, or if bubble view is null.
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Animates in the flyout for the given bubble, if available, and then hides it after some time.
+     */
+    @VisibleForTesting
+    void animateInFlyoutForBubble(Bubble bubble) {
+        if (!shouldShowFlyout(bubble)) {
             return;
         }
 
@@ -2209,25 +2216,22 @@
             }
 
             // Stop suppressing the dot now that the flyout has morphed into the dot.
-            bubbleView.removeDotSuppressionFlag(
+            bubble.getIconView().removeDotSuppressionFlag(
                     BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
 
-            mFlyout.setVisibility(INVISIBLE);
-
             // Hide the stack after a delay, if needed.
             updateTemporarilyInvisibleAnimation(false /* hideImmediately */);
         };
-        mFlyout.setVisibility(INVISIBLE);
 
         // Suppress the dot when we are animating the flyout.
-        bubbleView.addDotSuppressionFlag(
+        bubble.getIconView().addDotSuppressionFlag(
                 BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
 
         // Start flyout expansion. Post in case layout isn't complete and getWidth returns 0.
         post(() -> {
             // An auto-expanding bubble could have been posted during the time it takes to
             // layout.
-            if (isExpanded()) {
+            if (isExpanded() || bubble.getIconView() == null) {
                 return;
             }
             final Runnable expandFlyoutAfterDelay = () -> {
@@ -2244,18 +2248,21 @@
                 mFlyout.postDelayed(mAnimateInFlyout, 200);
             };
 
-            if (bubble.getIconView() == null) {
-                return;
-            }
 
-            mFlyout.setupFlyoutStartingAsDot(flyoutMessage,
-                    mStackAnimationController.getStackPosition(), getWidth(),
-                    mStackAnimationController.isStackOnLeftSide(),
-                    bubble.getIconView().getDotColor() /* dotColor */,
-                    expandFlyoutAfterDelay /* onLayoutComplete */,
-                    mAfterFlyoutHidden,
-                    bubble.getIconView().getDotCenter(),
-                    !bubble.showDot());
+            if (mFlyout.getVisibility() == View.VISIBLE) {
+                mFlyout.animateUpdate(bubble.getFlyoutMessage(), getWidth(),
+                        mStackAnimationController.getStackPosition().y);
+            } else {
+                mFlyout.setVisibility(INVISIBLE);
+                mFlyout.setupFlyoutStartingAsDot(bubble.getFlyoutMessage(),
+                        mStackAnimationController.getStackPosition(), getWidth(),
+                        mStackAnimationController.isStackOnLeftSide(),
+                        bubble.getIconView().getDotColor() /* dotColor */,
+                        expandFlyoutAfterDelay /* onLayoutComplete */,
+                        mAfterFlyoutHidden,
+                        bubble.getIconView().getDotCenter(),
+                        !bubble.showDot());
+            }
             mFlyout.bringToFront();
         });
         mFlyout.removeCallbacks(mHideFlyout);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/StackEducationView.kt b/packages/SystemUI/src/com/android/systemui/bubbles/StackEducationView.kt
index 9e7a2fb..216df2e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/StackEducationView.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/StackEducationView.kt
@@ -128,7 +128,7 @@
 
     private fun setShouldShow(shouldShow: Boolean) {
         context.getSharedPreferences(context.packageName, Context.MODE_PRIVATE)
-                .edit().putBoolean(PREF_MANAGED_EDUCATION, !shouldShow).apply()
+                .edit().putBoolean(PREF_STACK_EDUCATION, !shouldShow).apply()
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index fd73207..7fdc019 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -274,16 +274,14 @@
                 // Then, draw a line across the screen to the bubble's resting position.
                 path.lineTo(getBubbleLeft(index), expandedY);
             } else {
-                final float sideMultiplier =
-                        mLayout.isFirstChildXLeftOfCenter(mCollapsePoint.x) ? -1 : 1;
-                final float stackedX = mCollapsePoint.x + (sideMultiplier * index * mStackOffsetPx);
+                final float stackedX = mCollapsePoint.x;
 
                 // If we're collapsing, draw a line from the bubble's current position to the side
                 // of the screen where the bubble will be stacked.
                 path.lineTo(stackedX, expandedY);
 
                 // Then, draw a line down to the stack position.
-                path.lineTo(stackedX, mCollapsePoint.y);
+                path.lineTo(stackedX, mCollapsePoint.y + index * mStackOffsetPx);
             }
 
             // The lead bubble should be the bubble with the longest distance to travel when we're
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 4c902b9..1205124 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -744,15 +744,13 @@
 
     @Override
     float getOffsetForChainedPropertyAnimation(DynamicAnimation.ViewProperty property) {
-        if (property.equals(DynamicAnimation.TRANSLATION_X)) {
+        if (property.equals(DynamicAnimation.TRANSLATION_Y)) {
             // If we're in the dismiss target, have the bubbles pile on top of each other with no
             // offset.
             if (isStackStuckToTarget()) {
                 return 0f;
             } else {
-                // Offset to the left if we're on the left, or the right otherwise.
-                return mLayout.isFirstChildXLeftOfCenter(mStackPosition.x)
-                        ? -mStackOffset : mStackOffset;
+                return mStackOffset;
             }
         } else {
             return 0f;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeScope.java b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeScope.java
index 7a8b816..435859a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeScope.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeScope.java
@@ -24,7 +24,7 @@
 import javax.inject.Scope;
 
 /**
- * Scope annotation for singleton items within the StatusBarComponent.
+ * Scope annotation for singleton items within the DozeComponent.
  */
 @Documented
 @Retention(RUNTIME)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 0184fa7..dcee9fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -140,6 +140,8 @@
     private static final int MSG_SUPPRESS_AMBIENT_DISPLAY          = 56 << MSG_SHIFT;
     private static final int MSG_REQUEST_WINDOW_MAGNIFICATION_CONNECTION = 57 << MSG_SHIFT;
     private static final int MSG_HANDLE_WINDOW_MANAGER_LOGGING_COMMAND = 58 << MSG_SHIFT;
+    //TODO(b/169175022) Update name and when feature name is locked.
+    private static final int MSG_EMERGENCY_ACTION_LAUNCH_GESTURE      = 59 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -258,6 +260,11 @@
         default void showAssistDisclosure() { }
         default void startAssist(Bundle args) { }
         default void onCameraLaunchGestureDetected(int source) { }
+
+        /**
+         * Notifies SysUI that the emergency action gesture was detected.
+         */
+        default void onEmergencyActionLaunchGestureDetected() { }
         default void showPictureInPictureMenu() { }
         default void setTopAppHidesStatusBar(boolean topAppHidesStatusBar) { }
 
@@ -730,6 +737,14 @@
     }
 
     @Override
+    public void onEmergencyActionLaunchGestureDetected() {
+        synchronized (mLock) {
+            mHandler.removeMessages(MSG_EMERGENCY_ACTION_LAUNCH_GESTURE);
+            mHandler.obtainMessage(MSG_EMERGENCY_ACTION_LAUNCH_GESTURE).sendToTarget();
+        }
+    }
+
+    @Override
     public void addQsTile(ComponentName tile) {
         synchronized (mLock) {
             mHandler.obtainMessage(MSG_ADD_QS_TILE, tile).sendToTarget();
@@ -1186,6 +1201,10 @@
                         mCallbacks.get(i).onCameraLaunchGestureDetected(msg.arg1);
                     }
                     break;
+                case MSG_EMERGENCY_ACTION_LAUNCH_GESTURE:
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).onEmergencyActionLaunchGestureDetected();
+                    }
                 case MSG_SHOW_PICTURE_IN_PICTURE_MENU:
                     for (int i = 0; i < mCallbacks.size(); i++) {
                         mCallbacks.get(i).showPictureInPictureMenu();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 1fdf631a..ef4108b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -175,8 +175,8 @@
     }
 
     /**
-      * Update lock screen mode for testing different layouts
-      */
+     * Update lock screen mode for testing different layouts
+     */
     public void onLockScreenModeChanged(int mode) {
         mLockScreenMode = mode;
     }
@@ -241,6 +241,13 @@
         clockYDark = MathUtils.lerp(clockYBouncer, clockYDark, shadeExpansion);
 
         float darkAmount = mBypassEnabled && !mHasCustomClock ? 1.0f : mDarkAmount;
+
+        // TODO(b/12836565) - prototyping only adjustment
+        if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
+            // This will keep the clock at the top for AOD
+            darkAmount = 0f;
+        }
+
         return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mEmptyDragAmount);
     }
 
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 873d40f..88a387d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -69,6 +69,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -152,6 +153,7 @@
 import com.android.systemui.demomode.DemoMode;
 import com.android.systemui.demomode.DemoModeCommandReceiver;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.emergency.EmergencyGesture;
 import com.android.systemui.fragments.ExtensionFragmentListener;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -819,7 +821,7 @@
                     updateScrimController();
                 };
 
-
+        mActivityIntentHelper = new ActivityIntentHelper(mContext);
         DateTimeView.setReceiverHandler(timeTickHandler);
     }
 
@@ -833,8 +835,6 @@
             mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
         }
 
-        mActivityIntentHelper = new ActivityIntentHelper(mContext);
-
         mColorExtractor.addOnColorsChangedListener(this);
         mStatusBarStateController.addCallback(this,
                 SysuiStatusBarStateController.RANK_STATUS_BAR);
@@ -3980,6 +3980,27 @@
         }
     }
 
+    @Override
+    public void onEmergencyActionLaunchGestureDetected() {
+        // TODO (b/169793384) Polish the panic gesture to be just like its older brother, camera.
+        Intent emergencyIntent = new Intent(EmergencyGesture.ACTION_LAUNCH_EMERGENCY);
+        PackageManager pm = mContext.getPackageManager();
+        ResolveInfo resolveInfo = pm.resolveActivity(emergencyIntent, /*flags=*/0);
+        if (resolveInfo == null) {
+            Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
+            return;
+        }
+
+        if (mVibrator != null && mVibrator.hasVibrator()) {
+            mVibrator.vibrate(500L);
+        }
+
+        emergencyIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName,
+                resolveInfo.activityInfo.name));
+        emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        startActivity(emergencyIntent, /*dismissShade=*/true);
+    }
+
     boolean isCameraAllowedByAdmin() {
         if (mDevicePolicyManager.getCameraDisabled(null,
                 mLockscreenUserManager.getCurrentUserId())) {
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 2b4ed4e..d541c8f 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -70,6 +70,13 @@
             android:exported="false"
             android:resizeableActivity="true" />
 
+        <activity android:name="com.android.systemui.emergency.EmergencyActivityTest"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="com.android.systemui.action.LAUNCH_EMERGENCY"/>
+            </intent-filter>
+        </activity>
+
         <activity
             android:name="com.android.systemui.globalactions.GlobalActionsImeTest$TestActivity"
             android:excludeFromRecents="true"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index 5f2fd69..f1606c5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -224,11 +224,12 @@
 
 
     @Test
-    public void onDensityChanged_enabled_updateDimensionsAndLayout() {
+    public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() {
         mInstrumentation.runOnMainSync(() -> {
             mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
                     Float.NaN);
             Mockito.reset(mWindowManager);
+            Mockito.reset(mMirrorWindowControl);
         });
 
         mInstrumentation.runOnMainSync(() -> {
@@ -237,7 +238,9 @@
 
         verify(mResources, atLeastOnce()).getDimensionPixelSize(anyInt());
         verify(mWindowManager).removeView(any());
+        verify(mMirrorWindowControl).destroyControl();
         verify(mWindowManager).addView(any(), any());
+        verify(mMirrorWindowControl).showControl();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/emergency/EmergencyActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/emergency/EmergencyActivityTest.java
new file mode 100644
index 0000000..a52a598
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/emergency/EmergencyActivityTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 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.emergency;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.systemui.R;
+
+/**
+ * Test activity for resolving {@link EmergencyGesture#ACTION_LAUNCH_EMERGENCY} action.
+ */
+public class EmergencyActivityTest extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+}
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 a6ea9966a..d6a7acb 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
@@ -24,6 +24,7 @@
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.TestCase.fail;
 
+import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -34,6 +35,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -43,6 +45,7 @@
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
+import android.content.Intent;
 import android.content.IntentFilter;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.hardware.fingerprint.FingerprintManager;
@@ -84,6 +87,7 @@
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.emergency.EmergencyGesture;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
@@ -146,6 +150,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -873,6 +878,19 @@
         verify(mDozeServiceHost).setDozeSuppressed(false);
     }
 
+    @Test
+    public void onEmergencyActionLaunchGesture_launchesEmergencyIntent() {
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        StatusBar statusBarSpy = spy(mStatusBar);
+
+        statusBarSpy.onEmergencyActionLaunchGestureDetected();
+
+        verify(statusBarSpy).startActivity(intentCaptor.capture(), eq(true));
+        Intent sentIntent = intentCaptor.getValue();
+        assertEquals(sentIntent.getAction(), EmergencyGesture.ACTION_LAUNCH_EMERGENCY);
+
+    }
+
     public static class TestableNotificationInterruptStateProviderImpl extends
             NotificationInterruptStateProviderImpl {
 
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
index 86e6f11..da13e34 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
@@ -194,17 +194,16 @@
 
     @Test
     public void testRequestLastDownstreamAddress() throws Exception {
-        final int fakeHotspotSubAddr = 0x2b05;
-        final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
+        final int fakeHotspotSubAddr = 0x2b05; // 43.5
         when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
         final LinkAddress hotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
                 mHotspotIpServer, true /* useLastAddress */);
-        assertEquals("Wrong wifi prefix: ", predefinedPrefix, asIpPrefix(hotspotAddress));
+        assertEquals("Wrong wifi prefix: ", new LinkAddress("192.168.43.5/24"), hotspotAddress);
         when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddress);
 
         final LinkAddress usbAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
                 mUsbIpServer, true /* useLastAddress */);
-        assertNotEquals(predefinedPrefix, asIpPrefix(usbAddress));
+        assertEquals("Wrong wifi prefix: ", new LinkAddress("192.168.45.5/24"), usbAddress);
 
         mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
         mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
@@ -218,6 +217,18 @@
         final LinkAddress newUsbAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
                 mUsbIpServer, true /* useLastAddress */);
         assertEquals(usbAddress, newUsbAddress);
+
+        // BUG: the code should detect a conflict, but it doesn't.
+        // Regression introduced in r.android.com/168169687.
+        // Ensure conflict notification works when using cached address.
+        when(mHotspotIpServer.getAddress()).thenReturn(newHotspotAddress);
+        when(mUsbIpServer.getAddress()).thenReturn(usbAddress);
+        final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork,
+                new LinkAddress("192.168.88.23/16"), null,
+                makeNetworkCapabilities(TRANSPORT_WIFI));
+        mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream);
+        verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
+        verify(mUsbIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
     }
 
     private UpstreamNetworkState buildUpstreamNetworkState(final Network network,
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index d71b919..e1c4993 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2633,6 +2633,7 @@
     }
 
     @Override
+    @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
     public PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent,
             int flags) {
         return PendingIntent.getActivity(context, requestCode, intent, flags);
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
index a860db3..14af8c6 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
@@ -19,6 +19,7 @@
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_DOUBLE_TAP;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SINGLE_TAP;
+import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_DOWN;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_LEFT;
 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_RIGHT;
@@ -27,11 +28,13 @@
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_DOUBLE_TAP;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SINGLE_TAP;
+import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_DOWN;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_LEFT;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_RIGHT;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_UP;
 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_TRIPLE_TAP;
+import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_DOUBLE_TAP;
 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD;
 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_SINGLE_TAP;
@@ -140,6 +143,9 @@
         mMultiFingerGestures.add(
                 new MultiFingerMultiTap(mContext, 2, 1, GESTURE_2_FINGER_SINGLE_TAP, this));
         mMultiFingerGestures.add(
+                new MultiFingerMultiTapAndHold(
+                        mContext, 2, 1, GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD, this));
+        mMultiFingerGestures.add(
                 new MultiFingerMultiTap(mContext, 2, 2, GESTURE_2_FINGER_DOUBLE_TAP, this));
         mMultiFingerGestures.add(
                 new MultiFingerMultiTapAndHold(
@@ -153,9 +159,17 @@
                 new MultiFingerMultiTap(mContext, 3, 2, GESTURE_3_FINGER_DOUBLE_TAP, this));
         mMultiFingerGestures.add(
                 new MultiFingerMultiTapAndHold(
+                        mContext, 3, 1, GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD, this));
+        mMultiFingerGestures.add(
+                new MultiFingerMultiTapAndHold(
                         mContext, 3, 2, GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD, this));
         mMultiFingerGestures.add(
                 new MultiFingerMultiTap(mContext, 3, 3, GESTURE_3_FINGER_TRIPLE_TAP, this));
+        mMultiFingerGestures.add(
+                new MultiFingerMultiTapAndHold(
+                        mContext, 3, 3, GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD, this));
+        mMultiFingerGestures.add(
+                new MultiFingerMultiTap(mContext, 3, 3, GESTURE_3_FINGER_TRIPLE_TAP, this));
         // Four-finger taps.
         mMultiFingerGestures.add(
                 new MultiFingerMultiTap(mContext, 4, 1, GESTURE_4_FINGER_SINGLE_TAP, this));
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerMultiTap.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerMultiTap.java
index e15c495..46b4628 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerMultiTap.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerMultiTap.java
@@ -162,6 +162,7 @@
         // Accept down only before target number of fingers are down
         // or the finger count is not more than target.
         if ((currentFingerCount > mTargetFingerCount) || mIsTargetFingerCountReached) {
+            mIsTargetFingerCountReached = false;
             cancelGesture(event, rawEvent, policyFlags);
             return;
         }
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index b3d4085..95a7a22 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -38,7 +38,6 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.telecom.TelecomManager;
 import android.util.MutableBoolean;
 import android.util.Slog;
 import android.view.KeyEvent;
@@ -46,7 +45,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.server.LocalServices;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -529,15 +527,9 @@
                         "userSetupComplete = %s, performing panic gesture.",
                         userSetupComplete));
             }
-            // TODO(b/160006048): Not all devices have telephony. Check system feature first.
-            TelecomManager telecomManager = (TelecomManager) mContext.getSystemService(
-                    Context.TELECOM_SERVICE);
-            mContext.startActivity(telecomManager.createLaunchEmergencyDialerIntent(null).addFlags(
-                    Intent.FLAG_ACTIVITY_NEW_TASK
-                            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                            | Intent.FLAG_ACTIVITY_SINGLE_TOP).putExtra(
-                    "com.android.phone.EmergencyDialer.extra.ENTRY_TYPE",
-                    2)); // 2 maps to power button, forcing into fast emergency dialer experience.
+            StatusBarManagerInternal service = LocalServices.getService(
+                    StatusBarManagerInternal.class);
+            service.onEmergencyActionLaunchGestureDetected();
             return true;
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java
index cb7db92..c87f62f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java
+++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java
@@ -89,7 +89,8 @@
         }
     }
 
-    void onError(int sensorId, int cookie, int error, int vendorCode) throws RemoteException {
+    public void onError(int sensorId, int cookie, int error, int vendorCode)
+            throws RemoteException {
         if (mSensorReceiver != null) {
             mSensorReceiver.onError(sensorId, cookie, error, vendorCode);
         } else if (mFaceServiceReceiver != null) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/LockoutConsumer.java b/services/core/java/com/android/server/biometrics/sensors/LockoutConsumer.java
new file mode 100644
index 0000000..153bd46
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/LockoutConsumer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2020 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.biometrics.sensors;
+
+/**
+ * Interface that clients interested/eligible for lockout events should implement.
+ */
+public interface LockoutConsumer {
+    void onLockoutTimed(long durationMillis);
+    void onLockoutPermanent();
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java
index 42c7d16..3fdd279 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java
@@ -17,7 +17,6 @@
 package com.android.server.biometrics.sensors.face;
 
 import android.content.Context;
-import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.face.Face;
 import android.util.AtomicFile;
 import android.util.Slog;
@@ -41,7 +40,7 @@
  * Class managing the set of faces per user across device reboots.
  * @hide
  */
-public class FaceUserState extends BiometricUserState {
+public class FaceUserState extends BiometricUserState<Face> {
 
     private static final String TAG = "FaceState";
     private static final String FACE_FILE = "settings_face.xml";
@@ -72,19 +71,9 @@
     }
 
     @Override
-    public void addBiometric(BiometricAuthenticator.Identifier identifier) {
-        if (identifier instanceof Face) {
-            super.addBiometric(identifier);
-        } else {
-            Slog.w(TAG, "Attempted to add non-face identifier");
-        }
-    }
-
-    @Override
-    protected ArrayList getCopy(ArrayList array) {
-        ArrayList<Face> result = new ArrayList<>(array.size());
-        for (int i = 0; i < array.size(); i++) {
-            Face f = (Face) array.get(i);
+    protected ArrayList<Face> getCopy(ArrayList<Face> array) {
+        final ArrayList<Face> result = new ArrayList<>();
+        for (Face f : array) {
             result.add(new Face(f.getName(), f.getBiometricId(), f.getDeviceId()));
         }
         return result;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java
index 0197028..f47b228 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java
@@ -30,7 +30,7 @@
 /**
  * Utility class for dealing with faces and face settings.
  */
-public class FaceUtils implements BiometricUtils {
+public class FaceUtils implements BiometricUtils<Face> {
 
     private static final Object sInstanceLock = new Object();
     private static FaceUtils sInstance;
@@ -56,9 +56,8 @@
     }
 
     @Override
-    public void addBiometricForUser(Context ctx, int userId,
-            BiometricAuthenticator.Identifier identifier) {
-        getStateForUser(ctx, userId).addBiometric(identifier);
+    public void addBiometricForUser(Context ctx, int userId, Face face) {
+        getStateForUser(ctx, userId).addBiometric(face);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 45de538..dc22970 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -33,10 +33,9 @@
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.IBiometricSensorReceiver;
 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.ITestSession;
 import android.hardware.biometrics.fingerprint.IFingerprint;
 import android.hardware.biometrics.fingerprint.SensorProps;
-import android.hardware.biometrics.ITestService;
-import android.hardware.biometrics.SensorPropertiesInternal;
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
@@ -53,6 +52,8 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.EventLog;
 import android.util.Pair;
 import android.util.Slog;
@@ -91,54 +92,52 @@
     private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
     private final LockPatternUtils mLockPatternUtils;
     @NonNull private List<ServiceProvider> mServiceProviders;
-    @Nullable private TestService mTestService;
+    @NonNull private final ArrayMap<Integer, TestSession> mTestSessions;
 
-    private final class TestService extends ITestService.Stub {
+    private final class TestSession extends ITestSession.Stub {
+        private final int mSensorId;
 
-        @Override
-        public List<SensorPropertiesInternal> getSensorPropertiesInternal(
-                String opPackageName) {
-            Utils.checkPermission(getContext(), TEST_BIOMETRIC);
-            return null;
+        TestSession(int sensorId) {
+            mSensorId = sensorId;
         }
 
         @Override
-        public void enableTestHal(int sensorId, boolean enableTestHal) {
+        public void enableTestHal(boolean enableTestHal) {
             Utils.checkPermission(getContext(), TEST_BIOMETRIC);
         }
 
         @Override
-        public void enrollStart(int sensorId, int userId) {
+        public void startEnroll(int userId) {
             Utils.checkPermission(getContext(), TEST_BIOMETRIC);
         }
 
         @Override
-        public void enrollFinish(int sensorId, int userId) {
+        public void finishEnroll(int userId) {
             Utils.checkPermission(getContext(), TEST_BIOMETRIC);
         }
 
         @Override
-        public void authenticateSuccess(int sensorId, int userId)  {
+        public void acceptAuthentication(int userId)  {
             Utils.checkPermission(getContext(), TEST_BIOMETRIC);
         }
 
         @Override
-        public void authenticateReject(int sensorId, int userId)  {
+        public void rejectAuthentication(int userId)  {
             Utils.checkPermission(getContext(), TEST_BIOMETRIC);
         }
 
         @Override
-        public void notifyAcquired(int sensorId, int userId)  {
+        public void notifyAcquired(int userId)  {
             Utils.checkPermission(getContext(), TEST_BIOMETRIC);
         }
 
         @Override
-        public void notifyError(int sensorId, int userId)  {
+        public void notifyError(int userId)  {
             Utils.checkPermission(getContext(), TEST_BIOMETRIC);
         }
 
         @Override
-        public void internalCleanup(int sensorId, int userId)  {
+        public void cleanupInternalState(int userId)  {
             Utils.checkPermission(getContext(), TEST_BIOMETRIC);
         }
     }
@@ -148,15 +147,17 @@
      */
     private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
         @Override
-        public ITestService getTestService(String opPackageName) {
+        public ITestSession createTestSession(int sensorId, String opPackageName) {
             Utils.checkPermission(getContext(), TEST_BIOMETRIC);
 
-            synchronized (this) {
-                if (mTestService == null) {
-                    mTestService = new TestService();
+            final TestSession session;
+            synchronized (mTestSessions) {
+                if (!mTestSessions.containsKey(sensorId)) {
+                    mTestSessions.put(sensorId, new TestSession(sensorId));
                 }
+                session = mTestSessions.get(sensorId);
             }
-            return mTestService;
+            return session;
         }
 
         @Override // Binder call
@@ -620,6 +621,7 @@
         mLockoutResetDispatcher = new LockoutResetDispatcher(context);
         mLockPatternUtils = new LockPatternUtils(context);
         mServiceProviders = new ArrayList<>();
+        mTestSessions = new ArrayMap<>();
 
         initializeAidlHals();
     }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUserState.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUserState.java
index 56312bc..f32d28c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUserState.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUserState.java
@@ -17,7 +17,6 @@
 package com.android.server.biometrics.sensors.fingerprint;
 
 import android.content.Context;
-import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.fingerprint.Fingerprint;
 import android.util.AtomicFile;
 import android.util.Slog;
@@ -40,7 +39,7 @@
  * Class managing the set of fingerprint per user across device reboots.
  * @hide
  */
-public class FingerprintUserState extends BiometricUserState {
+public class FingerprintUserState extends BiometricUserState<Fingerprint> {
 
     private static final String TAG = "FingerprintState";
     private static final String FINGERPRINT_FILE = "settings_fingerprint.xml";
@@ -72,19 +71,9 @@
     }
 
     @Override
-    public void addBiometric(BiometricAuthenticator.Identifier identifier) {
-        if (identifier instanceof Fingerprint) {
-            super.addBiometric(identifier);
-        } else {
-            Slog.w(TAG, "Attempted to add non-fingerprint identifier");
-        }
-    }
-
-    @Override
-    protected ArrayList getCopy(ArrayList array) {
-        ArrayList<Fingerprint> result = new ArrayList<>();
-        for (int i = 0; i < array.size(); i++) {
-            Fingerprint fp = (Fingerprint) array.get(i);
+    protected ArrayList<Fingerprint> getCopy(ArrayList<Fingerprint> array) {
+        final ArrayList<Fingerprint> result = new ArrayList<>();
+        for (Fingerprint fp : array) {
             result.add(new Fingerprint(fp.getName(), fp.getGroupId(), fp.getBiometricId(),
                     fp.getDeviceId()));
         }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java
index f0bfe12..3bf3a5b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java
@@ -30,7 +30,7 @@
 /**
  * Utility class for dealing with fingerprints and fingerprint settings.
  */
-public class FingerprintUtils implements BiometricUtils {
+public class FingerprintUtils implements BiometricUtils<Fingerprint> {
 
     private static final Object sInstanceLock = new Object();
     private static FingerprintUtils sInstance;
@@ -56,9 +56,8 @@
     }
 
     @Override
-    public void addBiometricForUser(Context context, int userId,
-            BiometricAuthenticator.Identifier identifier) {
-        getStateForUser(context, userId).addBiometric(identifier);
+    public void addBiometricForUser(Context context, int userId, Fingerprint fingerprint) {
+        getStateForUser(context, userId).addBiometric(fingerprint);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
new file mode 100644
index 0000000..e923943
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2020 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.biometrics.sensors.fingerprint.aidl;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.TaskStackListener;
+import android.content.Context;
+import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricFingerprintConstants;
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.fingerprint.ISession;
+import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.sensors.AuthenticationClient;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.LockoutConsumer;
+import com.android.server.biometrics.sensors.LockoutTracker;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
+import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper;
+
+import java.util.ArrayList;
+
+/**
+ * Fingerprint-specific authentication client supporting the
+ * {@link android.hardware.biometrics.fingerprint.IFingerprint} AIDL interface.
+ */
+public class FingerprintAuthenticationClient extends AuthenticationClient<ISession> implements
+        Udfps, LockoutConsumer {
+    private static final String TAG = "FingerprintAuthenticationClient";
+
+    @NonNull private final LockoutCache mLockoutCache;
+    @Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
+    @Nullable private ICancellationSignal mCancellationSignal;
+
+    public FingerprintAuthenticationClient(@NonNull Context context,
+            @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
+            @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
+            boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
+            int sensorId, boolean isStrongBiometric, int statsClient,
+            @Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache,
+            @Nullable IUdfpsOverlayController udfpsOverlayController) {
+        super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner,
+                cookie, requireConfirmation, sensorId, isStrongBiometric,
+                BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
+                lockoutCache);
+        mLockoutCache = lockoutCache;
+        mUdfpsOverlayController = udfpsOverlayController;
+    }
+
+    @Override
+    public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
+            boolean authenticated, ArrayList<Byte> token) {
+        super.onAuthenticated(identifier, authenticated, token);
+
+        if (authenticated) {
+            UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+            mCallback.onClientFinished(this, true /* success */);
+        }
+    }
+
+    @Override
+    protected void startHalOperation() {
+        UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+        try {
+            mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+            onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
+                    0 /* vendorCode */);
+            UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+            mCallback.onClientFinished(this, false /* success */);
+        }
+    }
+
+    @Override
+    protected void stopHalOperation() {
+        UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+        try {
+            mCancellationSignal.cancel();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+            onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
+                    0 /* vendorCode */);
+            mCallback.onClientFinished(this, false /* success */);
+        }
+    }
+
+    @Override
+    public void onPointerDown(int x, int y, float minor, float major) {
+        try {
+            getFreshDaemon().onPointerDown(0 /* pointerId */, x, y, minor, major);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
+    }
+
+    @Override
+    public void onPointerUp() {
+        try {
+            getFreshDaemon().onPointerUp(0 /* pointerId */);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
+    }
+
+    @Override
+    public void onLockoutTimed(long durationMillis) {
+        mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED);
+        // Lockout metrics are logged as an error code.
+        final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
+        logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId());
+
+        try {
+            getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
+    }
+
+    @Override
+    public void onLockoutPermanent() {
+        mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT);
+        // Lockout metrics are logged as an error code.
+        final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
+        logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId());
+
+        try {
+            getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception", e);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 33f5418..c96bef1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.hardware.biometrics.BiometricFaceConstants;
 import android.hardware.biometrics.BiometricFingerprintConstants;
+import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.common.ICancellationSignal;
 import android.hardware.biometrics.fingerprint.ISession;
 import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -48,11 +49,12 @@
     public FingerprintEnrollClient(@NonNull Context context,
             @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
             @NonNull ClientMonitorCallbackConverter listener, int userId,
-            @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils,
-            int statsModality, int sensorId,
+            @NonNull byte[] hardwareAuthToken, @NonNull String owner,
+            @NonNull FingerprintUtils utils, int sensorId,
             @Nullable IUdfpsOverlayController udfpsOvelayController, int maxTemplatesPerUser) {
         super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
-                0 /* timeoutSec */, statsModality, sensorId, true /* shouldVibrate */);
+                0 /* timeoutSec */, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
+                true /* shouldVibrate */);
         mUdfpsOverlayController = udfpsOvelayController;
         mMaxTemplatesPerUser = maxTemplatesPerUser;
     }
@@ -83,7 +85,7 @@
     protected void startHalOperation() {
         UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
         try {
-            getFreshDaemon().enroll(mSequentialId,
+            mCancellationSignal = getFreshDaemon().enroll(mSequentialId,
                     HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken));
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception when requesting enroll", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 0b59086..bac83b9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -19,12 +19,14 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.app.IActivityTaskManager;
+import android.app.TaskStackListener;
 import android.content.Context;
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.fingerprint.IFingerprint;
 import android.hardware.biometrics.fingerprint.SensorProps;
 import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
 import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -37,12 +39,15 @@
 import android.util.SparseArray;
 import android.view.Surface;
 
+import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.sensors.AuthenticationClient;
 import com.android.server.biometrics.sensors.ClientMonitor;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
 import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
 import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
 import com.android.server.biometrics.sensors.fingerprint.ServiceProvider;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -52,6 +57,7 @@
 /**
  * Provider for a single instance of the {@link IFingerprint} HAL.
  */
+@SuppressWarnings("deprecation")
 public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvider {
 
     @NonNull private final Context mContext;
@@ -60,9 +66,48 @@
     @NonNull private final ClientMonitor.LazyDaemon<IFingerprint> mLazyDaemon;
     @NonNull private final Handler mHandler;
     @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
+    @NonNull private final IActivityTaskManager mActivityTaskManager;
+    @NonNull private final BiometricTaskStackListener mTaskStackListener;
 
     @Nullable private IUdfpsOverlayController mUdfpsOverlayController;
 
+    private final class BiometricTaskStackListener extends TaskStackListener {
+        @Override
+        public void onTaskStackChanged() {
+            mHandler.post(() -> {
+                for (int i = 0; i < mSensors.size(); i++) {
+                    final ClientMonitor<?> client = mSensors.get(i).getScheduler()
+                            .getCurrentClient();
+                    if (!(client instanceof AuthenticationClient)) {
+                        Slog.e(getTag(), "Task stack changed for client: " + client);
+                        continue;
+                    }
+                    if (Utils.isKeyguard(mContext, client.getOwnerString())) {
+                        continue; // Keyguard is always allowed
+                    }
+
+                    try {
+                        final List<ActivityManager.RunningTaskInfo> runningTasks =
+                                mActivityTaskManager.getTasks(1);
+                        if (!runningTasks.isEmpty()) {
+                            final String topPackage =
+                                    runningTasks.get(0).topActivity.getPackageName();
+                            if (!topPackage.contentEquals(client.getOwnerString())
+                                    && !client.isAlreadyDone()) {
+                                Slog.e(getTag(), "Stopping background authentication, top: "
+                                        + topPackage + " currentClient: " + client);
+                                mSensors.get(i).getScheduler()
+                                        .cancelAuthentication(client.getToken());
+                            }
+                        }
+                    } catch (RemoteException e) {
+                        Slog.e(getTag(), "Unable to get running tasks", e);
+                    }
+                }
+            });
+        }
+    }
+
     public FingerprintProvider(@NonNull Context context, @NonNull SensorProps[] props,
             @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
@@ -72,6 +117,8 @@
         mLazyDaemon = this::getHalInstance;
         mHandler = new Handler(Looper.getMainLooper());
         mLockoutResetDispatcher = lockoutResetDispatcher;
+        mActivityTaskManager = ActivityTaskManager.getService();
+        mTaskStackListener = new BiometricTaskStackListener();
 
         for (SensorProps prop : props) {
             final int sensorId = prop.commonProps.sensorId;
@@ -135,7 +182,7 @@
         mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback);
     }
 
-    private void scheduleCreateSessionWithoutHandler(@NonNull IFingerprint daemon, int sensorId,
+    private void createNewSessionWithoutHandler(@NonNull IFingerprint daemon, int sensorId,
             int userId) throws RemoteException {
         // Note that per IFingerprint createSession contract, this method will block until all
         // existing operations are canceled/finished. However, also note that this is fine, since
@@ -178,7 +225,7 @@
 
             try {
                 if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
-                    scheduleCreateSessionWithoutHandler(daemon, sensorId, userId);
+                    createNewSessionWithoutHandler(daemon, sensorId, userId);
                 }
 
                 final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(
@@ -222,19 +269,15 @@
             final IFingerprint daemon = getHalInstance();
             if (daemon == null) {
                 Slog.e(getTag(), "Null daemon during enroll, sensorId: " + sensorId);
-
-                try {
-                    receiver.onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE,
-                            0 /* vendorCode */);
-                } catch (RemoteException e) {
-                    Slog.e(getTag(), "Unable to send HW_UNAVAILABLE", e);
-                }
+                // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to
+                // this operation. We should not send the callback yet, since the scheduler may
+                // be processing something else.
                 return;
             }
 
             try {
                 if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
-                    scheduleCreateSessionWithoutHandler(daemon, sensorId, userId);
+                    createNewSessionWithoutHandler(daemon, sensorId, userId);
                 }
 
                 final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties()
@@ -242,8 +285,7 @@
                 final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext,
                         mSensors.get(sensorId).getLazySession(), token,
                         new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
-                        opPackageName, FingerprintUtils.getInstance(),
-                        BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
+                        opPackageName, FingerprintUtils.getInstance(), sensorId,
                         mUdfpsOverlayController, maxTemplatesPerUser);
                 scheduleForSensor(sensorId, client, new ClientMonitor.Callback() {
                     @Override
@@ -262,7 +304,7 @@
 
     @Override
     public void cancelEnrollment(int sensorId, @NonNull IBinder token) {
-
+        mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelEnrollment(token));
     }
 
     @Override
@@ -277,24 +319,74 @@
             int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
             @NonNull String opPackageName, boolean restricted, int statsClient,
             boolean isKeyguard) {
+        mHandler.post(() -> {
+            final IFingerprint daemon = getHalInstance();
+            if (daemon == null) {
+                Slog.e(getTag(), "Null daemon during authenticate, sensorId: " + sensorId);
+                // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to
+                // this operation. We should not send the callback yet, since the scheduler may
+                // be processing something else.
+                return;
+            }
 
+            try {
+                if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
+                    createNewSessionWithoutHandler(daemon, sensorId, userId);
+                }
+
+                final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
+                final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
+                        mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
+                        operationId, restricted, opPackageName, cookie,
+                        false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
+                        mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
+                        mUdfpsOverlayController);
+                mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+            } catch (RemoteException e) {
+                Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
+            }
+        });
     }
 
     @Override
     public void startPreparedClient(int sensorId, int cookie) {
-
+        mHandler.post(() -> mSensors.get(sensorId).getScheduler().startPreparedClient(cookie));
     }
 
     @Override
     public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
-
+        mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelAuthentication(token));
     }
 
     @Override
     public void scheduleRemove(int sensorId, @NonNull IBinder token,
             @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,
             @NonNull String opPackageName) {
+        mHandler.post(() -> {
+            final IFingerprint daemon = getHalInstance();
+            if (daemon == null) {
+                Slog.e(getTag(), "Null daemon during remove, sensorId: " + sensorId);
+                // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to
+                // this operation. We should not send the callback yet, since the scheduler may
+                // be processing something else.
+                return;
+            }
 
+            try {
+                if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
+                    createNewSessionWithoutHandler(daemon, sensorId, userId);
+                }
+
+                final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext,
+                        mSensors.get(sensorId).getLazySession(), token,
+                        new ClientMonitorCallbackConverter(receiver), fingerId, userId,
+                        opPackageName, FingerprintUtils.getInstance(), sensorId,
+                        mSensors.get(sensorId).getAuthenticatorIds());
+                mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+            } catch (RemoteException e) {
+                Slog.e(getTag(), "Remote exception when scheduling remove", e);
+            }
+        });
     }
 
     @Override
@@ -320,7 +412,7 @@
 
     @Override
     public int getLockoutModeForUser(int sensorId, int userId) {
-        return 0;
+        return mSensors.get(sensorId).getLockoutCache().getLockoutModeForUser(userId);
     }
 
     @Override
@@ -330,12 +422,24 @@
 
     @Override
     public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
-
+        final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient();
+        if (!(client instanceof Udfps)) {
+            Slog.e(getTag(), "onPointerDown received during client: " + client);
+            return;
+        }
+        final Udfps udfps = (Udfps) client;
+        udfps.onPointerDown(x, y, minor, major);
     }
 
     @Override
     public void onPointerUp(int sensorId) {
-
+        final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient();
+        if (!(client instanceof Udfps)) {
+            Slog.e(getTag(), "onPointerUp received during client: " + client);
+            return;
+        }
+        final Udfps udfps = (Udfps) client;
+        udfps.onPointerUp();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java
new file mode 100644
index 0000000..df063dc
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 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.biometrics.sensors.fingerprint.aidl;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.fingerprint.ISession;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.RemovalClient;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
+
+import java.util.Map;
+
+/**
+ * Fingerprint-specific removal client supporting the
+ * {@link android.hardware.biometrics.fingerprint.IFingerprint} interface.
+ */
+public class FingerprintRemovalClient extends RemovalClient<ISession> {
+    private static final String TAG = "FingerprintRemovalClient";
+
+    public FingerprintRemovalClient(@NonNull Context context,
+            @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
+            @NonNull ClientMonitorCallbackConverter listener, int biometricId, int userId,
+            @NonNull String owner, @NonNull FingerprintUtils utils, int sensorId,
+            @NonNull Map<Integer, Long> authenticatorIds) {
+        super(context, lazyDaemon, token, listener, biometricId, userId, owner, utils, sensorId,
+                authenticatorIds, BiometricsProtoEnums.MODALITY_FINGERPRINT);
+    }
+
+    @Override
+    protected void startHalOperation() {
+        try {
+            final int[] ids = new int[] {mBiometricId};
+            getFreshDaemon().removeEnrollments(mSequentialId, ids);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception when requesting remove", e);
+            mCallback.onClientFinished(this, false /* success */);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index 2ed695d..b7aa2d5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -37,12 +37,15 @@
 import com.android.server.biometrics.sensors.BiometricScheduler;
 import com.android.server.biometrics.sensors.ClientMonitor;
 import com.android.server.biometrics.sensors.Interruptable;
+import com.android.server.biometrics.sensors.LockoutConsumer;
 import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
 import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Maintains the state of a single sensor within an instance of the
@@ -55,6 +58,7 @@
     @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
     @NonNull private final BiometricScheduler mScheduler;
     @NonNull private final LockoutCache mLockoutCache;
+    @NonNull private final Map<Integer, Long> mAuthenticatorIds;
 
     @Nullable private Session mCurrentSession; // TODO: Death recipient
     @NonNull private final ClientMonitor.LazyDaemon<ISession> mLazySession;
@@ -84,6 +88,7 @@
         mSensorProperties = sensorProperties;
         mScheduler = new BiometricScheduler(tag, gestureAvailabilityDispatcher);
         mLockoutCache = new LockoutCache();
+        mAuthenticatorIds = new HashMap<>();
         mLazySession = () -> mCurrentSession != null ? mCurrentSession.mSession : null;
     }
 
@@ -209,12 +214,32 @@
 
             @Override
             public void onLockoutTimed(long durationMillis) {
+                mHandler.post(() -> {
+                    final ClientMonitor<?> client = mScheduler.getCurrentClient();
+                    if (!(client instanceof LockoutConsumer)) {
+                        Slog.e(mTag, "onLockoutTimed for non-lockout consumer: "
+                                + Utils.getClientName(client));
+                        return;
+                    }
 
+                    final LockoutConsumer lockoutConsumer = (LockoutConsumer) client;
+                    lockoutConsumer.onLockoutTimed(durationMillis);
+                });
             }
 
             @Override
             public void onLockoutPermanent() {
+                mHandler.post(() -> {
+                    final ClientMonitor<?> client = mScheduler.getCurrentClient();
+                    if (!(client instanceof LockoutConsumer)) {
+                        Slog.e(mTag, "onLockoutPermanent for non-lockout consumer: "
+                                + Utils.getClientName(client));
+                        return;
+                    }
 
+                    final LockoutConsumer lockoutConsumer = (LockoutConsumer) client;
+                    lockoutConsumer.onLockoutPermanent();
+                });
             }
 
             @Override
@@ -270,4 +295,8 @@
     @NonNull LockoutCache getLockoutCache() {
         return mLockoutCache;
     }
+
+    @NonNull Map<Integer, Long> getAuthenticatorIds() {
+        return mAuthenticatorIds;
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index fedcfa5..da68bc8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -594,16 +594,12 @@
 
     @Override
     public void startPreparedClient(int sensorId, int cookie) {
-        mHandler.post(() -> {
-            mScheduler.startPreparedClient(cookie);
-        });
+        mHandler.post(() -> mScheduler.startPreparedClient(cookie));
     }
 
     @Override
     public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
-        mHandler.post(() -> {
-            mScheduler.cancelAuthentication(token);
-        });
+        mHandler.post(() -> mScheduler.cancelAuthentication(token));
     }
 
     @Override
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index 5206571..179fb7d 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -23,15 +23,12 @@
 import static android.location.LocationManager.KEY_LOCATION_CHANGED;
 import static android.location.LocationManager.KEY_PROVIDER_ENABLED;
 import static android.location.LocationManager.PASSIVE_PROVIDER;
-import static android.location.LocationRequest.PASSIVE_INTERVAL;
 import static android.os.IPowerManager.LOCATION_MODE_NO_CHANGE;
 import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF;
 import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
 import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF;
 import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
 
-import static com.android.internal.location.ProviderRequest.EMPTY_REQUEST;
-import static com.android.internal.location.ProviderRequest.INTERVAL_DISABLED;
 import static com.android.server.location.LocationManagerService.D;
 import static com.android.server.location.LocationManagerService.TAG;
 import static com.android.server.location.LocationPermissions.PERMISSION_COARSE;
@@ -503,14 +500,7 @@
             LocationRequest.Builder builder = new LocationRequest.Builder(baseRequest);
 
             if (mPermissionLevel < PERMISSION_FINE) {
-                switch (baseRequest.getQuality()) {
-                    case LocationRequest.ACCURACY_FINE:
-                        builder.setQuality(LocationRequest.ACCURACY_BLOCK);
-                        break;
-                    case LocationRequest.POWER_HIGH:
-                        builder.setQuality(LocationRequest.POWER_LOW);
-                        break;
-                }
+                builder.setQuality(LocationRequest.QUALITY_LOW_POWER);
                 if (baseRequest.getIntervalMillis() < MIN_COARSE_INTERVAL_MS) {
                     builder.setIntervalMillis(MIN_COARSE_INTERVAL_MS);
                 }
@@ -1709,7 +1699,7 @@
     @Override
     protected boolean registerWithService(ProviderRequest request,
             Collection<Registration> registrations) {
-        return reregisterWithService(EMPTY_REQUEST, request, registrations);
+        return reregisterWithService(ProviderRequest.EMPTY_REQUEST, request, registrations);
     }
 
     @GuardedBy("mLock")
@@ -1778,8 +1768,8 @@
             Preconditions.checkState(Thread.holdsLock(mLock));
         }
 
-        mLocationEventLog.logProviderUpdateRequest(mName, EMPTY_REQUEST);
-        mProvider.setRequest(EMPTY_REQUEST);
+        mLocationEventLog.logProviderUpdateRequest(mName, ProviderRequest.EMPTY_REQUEST);
+        mProvider.setRequest(ProviderRequest.EMPTY_REQUEST);
     }
 
     @GuardedBy("mLock")
@@ -1839,27 +1829,27 @@
             Preconditions.checkState(Thread.holdsLock(mLock));
         }
 
-        long intervalMs = INTERVAL_DISABLED;
+        long intervalMs = ProviderRequest.INTERVAL_DISABLED;
+        int quality = LocationRequest.QUALITY_LOW_POWER;
         boolean locationSettingsIgnored = false;
         boolean lowPower = true;
-        ArrayList<LocationRequest> locationRequests = new ArrayList<>(registrations.size());
 
         for (Registration registration : registrations) {
             LocationRequest request = registration.getRequest();
 
             // passive requests do not contribute to the provider request
-            if (request.getIntervalMillis() == PASSIVE_INTERVAL) {
+            if (request.getIntervalMillis() == LocationRequest.PASSIVE_INTERVAL) {
                 continue;
             }
 
             intervalMs = min(request.getIntervalMillis(), intervalMs);
+            quality = min(request.getQuality(), quality);
             locationSettingsIgnored |= request.isLocationSettingsIgnored();
             lowPower &= request.isLowPower();
-            locationRequests.add(request);
         }
 
-        if (intervalMs == INTERVAL_DISABLED) {
-            return EMPTY_REQUEST;
+        if (intervalMs == ProviderRequest.INTERVAL_DISABLED) {
+            return ProviderRequest.EMPTY_REQUEST;
         }
 
         // calculate who to blame for power in a somewhat arbitrary fashion. we pick a threshold
@@ -1872,7 +1862,7 @@
         } catch (ArithmeticException e) {
             // check for and handle overflow by setting to one below the passive interval so passive
             // requests are automatically skipped
-            thresholdIntervalMs = PASSIVE_INTERVAL - 1;
+            thresholdIntervalMs = LocationRequest.PASSIVE_INTERVAL - 1;
         }
 
         WorkSource workSource = new WorkSource();
@@ -1884,9 +1874,9 @@
 
         return new ProviderRequest.Builder()
                 .setIntervalMillis(intervalMs)
+                .setQuality(quality)
                 .setLocationSettingsIgnored(locationSettingsIgnored)
                 .setLowPower(lowPower)
-                .setLocationRequests(locationRequests)
                 .setWorkSource(workSource)
                 .build();
     }
diff --git a/services/core/java/com/android/server/location/PassiveLocationProviderManager.java b/services/core/java/com/android/server/location/PassiveLocationProviderManager.java
index fc10d5f..b771861 100644
--- a/services/core/java/com/android/server/location/PassiveLocationProviderManager.java
+++ b/services/core/java/com/android/server/location/PassiveLocationProviderManager.java
@@ -63,15 +63,7 @@
 
     @Override
     protected ProviderRequest mergeRegistrations(Collection<Registration> registrations) {
-        boolean locationSettingsIgnored = false;
-        for (Registration registration : registrations) {
-            locationSettingsIgnored |= registration.getRequest().isLocationSettingsIgnored();
-        }
-
-        return new ProviderRequest.Builder()
-                .setIntervalMillis(0)
-                .setLocationSettingsIgnored(locationSettingsIgnored)
-                .build();
+        return new ProviderRequest.Builder().setIntervalMillis(0).build();
     }
 
     @Override
@@ -79,4 +71,9 @@
             Collection<Registration> registrations) {
         return 0;
     }
+
+    @Override
+    protected String getServiceState() {
+        return mProvider.getCurrentRequest().isActive() ? "registered" : "unregistered";
+    }
 }
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index e144b40..e25e605 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -708,12 +708,12 @@
             // For fast GNSS TTFF
             provider = LocationManager.NETWORK_PROVIDER;
             locationListener = mNetworkLocationListener;
-            locationRequest.setQuality(LocationRequest.POWER_LOW);
+            locationRequest.setQuality(LocationRequest.QUALITY_LOW_POWER);
         } else {
             // For Device-Based Hybrid (E911)
             provider = LocationManager.FUSED_PROVIDER;
             locationListener = mFusedLocationListener;
-            locationRequest.setQuality(LocationRequest.ACCURACY_FINE);
+            locationRequest.setQuality(LocationRequest.QUALITY_HIGH_ACCURACY);
         }
 
         // Ignore location settings if in emergency mode. This is only allowed for
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 23798c0..03bf74f 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4769,7 +4769,7 @@
 
         @Override
         public List<ComponentName> getEnabledNotificationListeners(int userId) {
-            checkCallerIsSystem();
+            checkNotificationListenerAccess();
             return mListeners.getAllowedComponents(userId);
         }
 
@@ -4838,7 +4838,7 @@
         public void setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId,
                 boolean granted) {
             Objects.requireNonNull(listener);
-            checkCallerIsSystemOrShell();
+            checkNotificationListenerAccess();
             final long identity = Binder.clearCallingIdentity();
             try {
                 if (mAllowedManagedServicePackages.test(
@@ -5111,6 +5111,14 @@
         }
     };
 
+    protected void checkNotificationListenerAccess() {
+        if (!isCallerSystemOrPhone()) {
+            getContext().enforceCallingPermission(
+                    permission.MANAGE_NOTIFICATION_LISTENERS,
+                    "Caller must hold " + permission.MANAGE_NOTIFICATION_LISTENERS);
+        }
+    }
+
     @VisibleForTesting
     protected void setNotificationAssistantAccessGrantedForUserInternal(
             ComponentName assistant, int baseUserId, boolean granted) {
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index ad022c7..7992fea 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -777,12 +777,15 @@
         void registerApkInApex(AndroidPackage pkg) {
             synchronized (mLock) {
                 for (ActiveApexInfo aai : mActiveApexInfosCache) {
-                    if (pkg.getBaseApkPath().startsWith(aai.apexDirectory.getAbsolutePath())) {
+                    if (pkg.getBaseApkPath().startsWith(
+                            aai.apexDirectory.getAbsolutePath() + File.separator)) {
                         List<String> apks = mApksInApex.get(aai.apexModuleName);
                         if (apks == null) {
                             apks = Lists.newArrayList();
                             mApksInApex.put(aai.apexModuleName, apks);
                         }
+                        Slog.i(TAG, "Registering " + pkg.getPackageName() + " as apk-in-apex of "
+                                + aai.apexModuleName);
                         apks.add(pkg.getPackageName());
                     }
                 }
diff --git a/services/core/java/com/android/server/pm/IncrementalStates.java b/services/core/java/com/android/server/pm/IncrementalStates.java
index dda5faf..ababb83 100644
--- a/services/core/java/com/android/server/pm/IncrementalStates.java
+++ b/services/core/java/com/android/server/pm/IncrementalStates.java
@@ -376,10 +376,10 @@
                 case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR:
                     // fall through
                 case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: {
-                    return PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT;
+                    return PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR;
                 }
                 case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: {
-                    return PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE;
+                    return PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE;
                 }
                 default:
                     return PackageManager.UNSTARTABLE_REASON_UNKNOWN;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 805fbbc..bf6a136 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17333,7 +17333,7 @@
             Bundle extras = new Bundle();
             extras.putInt(Intent.EXTRA_UID, mUid);
             extras.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName);
-            extras.putInt(Intent.EXTRA_REASON, reason);
+            extras.putInt(Intent.EXTRA_UNSTARTABLE_REASON, reason);
             // send broadcast to users with this app installed
             sendPackageBroadcast(Intent.ACTION_PACKAGE_UNSTARTABLE, mPackageName,
                     extras, 0 /*flags*/,
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index c086017..fedbed2 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -32,6 +32,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PermissionInfo;
 import android.content.pm.parsing.component.ParsedPermission;
+import android.os.Build;
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.Slog;
@@ -445,36 +446,38 @@
         return null;
     }
 
-    public @Nullable PermissionInfo generatePermissionInfo(@NonNull String groupName, int flags) {
-        if (groupName == null) {
-            if (perm == null || perm.getGroup() == null) {
-                return generatePermissionInfo(protectionLevel, flags);
-            }
-        } else {
-            if (perm != null && groupName.equals(perm.getGroup())) {
-                return PackageInfoUtils.generatePermissionInfo(perm, flags);
-            }
-        }
-        return null;
+    @Nullable
+    public String getGroup() {
+        return perm != null ? perm.getGroup() : null;
     }
 
-    public @NonNull PermissionInfo generatePermissionInfo(int adjustedProtectionLevel, int flags) {
+    @NonNull
+    public PermissionInfo generatePermissionInfo(int flags) {
+        return generatePermissionInfo(flags, Build.VERSION_CODES.CUR_DEVELOPMENT);
+    }
+
+    @NonNull
+    public PermissionInfo generatePermissionInfo(int flags, int targetSdkVersion) {
         PermissionInfo permissionInfo;
         if (perm != null) {
-            final boolean protectionLevelChanged = protectionLevel != adjustedProtectionLevel;
             permissionInfo = PackageInfoUtils.generatePermissionInfo(perm, flags);
-            if (protectionLevelChanged) {
-                // if we return different protection level, don't use the cached info
-                permissionInfo = new PermissionInfo(permissionInfo);
-                permissionInfo.protectionLevel = adjustedProtectionLevel;
-            }
-            return permissionInfo;
+        } else {
+            permissionInfo = new PermissionInfo();
+            permissionInfo.name = name;
+            permissionInfo.packageName = sourcePackageName;
+            permissionInfo.nonLocalizedLabel = name;
         }
-        permissionInfo = new PermissionInfo();
-        permissionInfo.name = name;
-        permissionInfo.packageName = sourcePackageName;
-        permissionInfo.nonLocalizedLabel = name;
-        permissionInfo.protectionLevel = protectionLevel;
+        if (targetSdkVersion >= Build.VERSION_CODES.O) {
+            permissionInfo.protectionLevel = protectionLevel;
+        } else {
+            final int protection = protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
+            if (protection == PermissionInfo.PROTECTION_SIGNATURE) {
+                // Signature permission's protection flags are always reported.
+                permissionInfo.protectionLevel = protectionLevel;
+            } else {
+                permissionInfo.protectionLevel = protection;
+            }
+        }
         return permissionInfo;
     }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 25e1848..45872a8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -544,24 +544,37 @@
 
     @Override
     @Nullable
-    public PermissionInfo getPermissionInfo(String permName, String packageName,
+    public PermissionInfo getPermissionInfo(@NonNull String permName, @NonNull String opPackageName,
             @PermissionInfoFlags int flags) {
         final int callingUid = getCallingUid();
         if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
             return null;
         }
-        final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
+        final AndroidPackage opPackage = mPackageManagerInt.getPackage(opPackageName);
+        final int targetSdkVersion = getPermissionInfoCallingTargetSdkVersion(opPackage,
+                callingUid);
         synchronized (mLock) {
             final BasePermission bp = mSettings.getPermissionLocked(permName);
             if (bp == null) {
                 return null;
             }
-            final int adjustedProtectionLevel = adjustPermissionProtectionFlagsLocked(
-                    bp.getProtectionLevel(), pkg, callingUid);
-            return bp.generatePermissionInfo(adjustedProtectionLevel, flags);
+            return bp.generatePermissionInfo(flags, targetSdkVersion);
         }
     }
 
+    private int getPermissionInfoCallingTargetSdkVersion(@Nullable AndroidPackage pkg, int uid) {
+        final int appId = UserHandle.getAppId(uid);
+        if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID
+                || appId == Process.SHELL_UID) {
+            // System sees all flags.
+            return Build.VERSION_CODES.CUR_DEVELOPMENT;
+        }
+        if (pkg == null) {
+            return Build.VERSION_CODES.CUR_DEVELOPMENT;
+        }
+        return pkg.getTargetSdkVersion();
+    }
+
     @Override
     @Nullable
     public ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String groupName,
@@ -576,9 +589,8 @@
             }
             final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
             for (BasePermission bp : mSettings.mPermissions.values()) {
-                final PermissionInfo pi = bp.generatePermissionInfo(groupName, flags);
-                if (pi != null) {
-                    out.add(pi);
+                if (Objects.equals(bp.getGroup(), groupName)) {
+                    out.add(bp.generatePermissionInfo(flags));
                 }
             }
             return new ParceledListSlice<>(out);
@@ -2235,32 +2247,6 @@
         }
     }
 
-    private int adjustPermissionProtectionFlagsLocked(int protectionLevel,
-            @Nullable AndroidPackage pkg, int uid) {
-        // Signature permission flags area always reported
-        final int protectionLevelMasked = protectionLevel
-                & (PermissionInfo.PROTECTION_NORMAL
-                | PermissionInfo.PROTECTION_DANGEROUS
-                | PermissionInfo.PROTECTION_SIGNATURE);
-        if (protectionLevelMasked == PermissionInfo.PROTECTION_SIGNATURE) {
-            return protectionLevel;
-        }
-        // System sees all flags.
-        final int appId = UserHandle.getAppId(uid);
-        if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID
-                || appId == Process.SHELL_UID) {
-            return protectionLevel;
-        }
-        if (pkg == null) {
-            return protectionLevel;
-        }
-        if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.O) {
-            return protectionLevelMasked;
-        }
-        // Apps that target O see flags for all protection levels.
-        return protectionLevel;
-    }
-
     /**
      * We might auto-grant permissions if any permission of the group is already granted. Hence if
      * the group of a granted permission changes we need to revoke it to avoid having permissions of
@@ -4903,8 +4889,7 @@
                     BasePermission bp = mSettings.mPermissions.valueAt(i);
 
                     if (bp.perm != null && bp.perm.getProtection() == protection) {
-                        matchingPermissions.add(
-                                PackageInfoUtils.generatePermissionInfo(bp.perm, 0));
+                        matchingPermissions.add(bp.generatePermissionInfo(0));
                     }
                 }
             }
@@ -4925,8 +4910,7 @@
 
                     if (bp.perm != null && (bp.perm.getProtectionFlags() & protectionFlags)
                             == protectionFlags) {
-                        matchingPermissions.add(
-                                PackageInfoUtils.generatePermissionInfo(bp.perm, 0));
+                        matchingPermissions.add(bp.generatePermissionInfo(0));
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index e0b671f..f43a4ce 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1630,13 +1630,14 @@
             if (modemInfo == null) {
                 return StatsManager.PULL_SKIP;
             }
-            pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, modemInfo.getTimestamp(),
+            pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
+                    modemInfo.getTimestampMillis(),
                     modemInfo.getSleepTimeMillis(), modemInfo.getIdleTimeMillis(),
-                    modemInfo.getTransmitPowerInfo().get(0).getTimeInMillis(),
-                    modemInfo.getTransmitPowerInfo().get(1).getTimeInMillis(),
-                    modemInfo.getTransmitPowerInfo().get(2).getTimeInMillis(),
-                    modemInfo.getTransmitPowerInfo().get(3).getTimeInMillis(),
-                    modemInfo.getTransmitPowerInfo().get(4).getTimeInMillis(),
+                    modemInfo.getTransmitDurationMillisAtPowerLevel(0),
+                    modemInfo.getTransmitDurationMillisAtPowerLevel(1),
+                    modemInfo.getTransmitDurationMillisAtPowerLevel(2),
+                    modemInfo.getTransmitDurationMillisAtPowerLevel(3),
+                    modemInfo.getTransmitDurationMillisAtPowerLevel(4),
                     modemInfo.getReceiveTimeMillis(),
                     -1 /*`energy_used` field name deprecated, use -1 to indicate as unused.*/));
         } finally {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index e9215f9..ebfffec 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -86,6 +86,13 @@
     void toggleSplitScreen();
     void appTransitionFinished(int displayId);
 
+    /**
+     * Notifies the status bar that a Emergency Action launch gesture has been detected.
+     *
+     * TODO (b/169175022) Update method name and docs when feature name is locked.
+     */
+    void onEmergencyActionLaunchGestureDetected();
+
     void toggleRecentApps();
 
     void setCurrentUser(int newUserId);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 6a68dc1..55cb7f3 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -264,6 +264,23 @@
             }
         }
 
+        /**
+         * Notifies the status bar that a Emergency Action launch gesture has been detected.
+         *
+         * TODO (b/169175022) Update method name and docs when feature name is locked.
+         */
+        @Override
+        public void onEmergencyActionLaunchGestureDetected() {
+            if (SPEW) Slog.d(TAG, "Launching emergency action");
+            if (mBar != null) {
+                try {
+                    mBar.onEmergencyActionLaunchGestureDetected();
+                } catch (RemoteException e) {
+                    if (SPEW) Slog.d(TAG, "Failed to launch emergency action");
+                }
+            }
+        }
+
         @Override
         public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
             StatusBarManagerService.this.topAppWindowChanged(displayId, isFullscreen, isImmersive);
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 143b657..470c2b1 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -531,7 +531,7 @@
                     // event. This is used to omit Surfaces from occlusion detection.
                     populateOverlayInputInfo(mInvalidInputWindow, w.getName(), type, isVisible);
                     mInputTransaction.setInputWindowInfo(
-                            w.mWinAnimator.mSurfaceController.getClientViewRootSurface(),
+                            w.mWinAnimator.mSurfaceController.mSurfaceControl,
                             mInvalidInputWindow);
                     return;
                 }
@@ -600,8 +600,7 @@
 
             if (w.mWinAnimator.hasSurface()) {
                 mInputTransaction.setInputWindowInfo(
-                    w.mWinAnimator.mSurfaceController.getClientViewRootSurface(),
-                    inputWindowHandle);
+                        w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 1fdb49f..02230d6 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -204,15 +204,14 @@
             int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
             ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
-            SurfaceControl outBLASTSurfaceControl) {
+            InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
                 + Binder.getCallingPid());
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
         int res = mService.relayoutWindow(this, window, attrs,
                 requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
                 outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
-                outActiveControls, outSurfaceSize, outBLASTSurfaceControl);
+                outActiveControls, outSurfaceSize);
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
                 + Binder.getCallingPid());
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0077182..a66a2c4 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4773,9 +4773,11 @@
             // If the task is not yet visible when it is added to the task organizer, then we should
             // hide it to allow the task organizer to show it when it is properly reparented. We
             // skip this for tasks created by the organizer because they can synchronously update
-            // the leash before new children are added to the task.
+            // the leash before new children are added to the task.  Also skip this if the task
+            // has already been sent to the organizer which can happen before the first draw if
+            // an existing task is reported to the organizer when it first registers.
             if (!mAtmService.getTransitionController().isShellTransitionsEnabled()
-                    && !mCreatedByOrganizer
+                    && !mCreatedByOrganizer && !mTaskAppearedSent
                     && mTaskOrganizer != null && !prevHasBeenVisible) {
                 getSyncTransaction().hide(getSurfaceControl());
                 commitPendingTransaction();
@@ -4827,6 +4829,11 @@
 
     @VisibleForTesting
     boolean setTaskOrganizer(ITaskOrganizer organizer) {
+        return setTaskOrganizer(organizer, false /* skipTaskAppeared */);
+    }
+
+    @VisibleForTesting
+    boolean setTaskOrganizer(ITaskOrganizer organizer, boolean skipTaskAppeared) {
         if (mTaskOrganizer == organizer) {
             return false;
         }
@@ -4839,7 +4846,9 @@
         sendTaskVanished(prevOrganizer);
 
         if (mTaskOrganizer != null) {
-            sendTaskAppeared();
+            if (!skipTaskAppeared) {
+                sendTaskAppeared();
+            }
         } else {
             // No longer managed by any organizer.
             mTaskAppearedSent = false;
@@ -4852,6 +4861,10 @@
         return true;
     }
 
+    boolean updateTaskOrganizerState(boolean forceUpdate) {
+        return updateTaskOrganizerState(forceUpdate, false /* skipTaskAppeared */);
+    }
+
     /**
      * Called when the task state changes (ie. from windowing mode change) an the task organizer
      * state should also be updated.
@@ -4859,9 +4872,10 @@
      * @param forceUpdate Updates the task organizer to the one currently specified in the task
      *                    org controller for the task's windowing mode, ignoring the cached
      *                    windowing mode checks.
+     * @param skipTaskAppeared Skips calling taskAppeared for the new organizer if it has changed
      * @return {@code true} if task organizer changed.
      */
-    boolean updateTaskOrganizerState(boolean forceUpdate) {
+    boolean updateTaskOrganizerState(boolean forceUpdate, boolean skipTaskAppeared) {
         if (getSurfaceControl() == null) {
             // Can't call onTaskAppeared without a surfacecontrol, so defer this until after one
             // is created.
@@ -4877,7 +4891,7 @@
         if (!forceUpdate && mTaskOrganizer == organizer) {
             return false;
         }
-        return setTaskOrganizer(organizer);
+        return setTaskOrganizer(organizer, skipTaskAppeared);
     }
 
     @Override
@@ -5864,7 +5878,11 @@
         final TaskDisplayArea taskDisplayArea = getDisplayArea();
 
         // If the top activity is the resumed one, nothing to do.
+        // For devices that are not in fullscreen mode (e.g. freeform windows), it's possible
+        // we still want to proceed if the visibility of other windows have changed (e.g. bringing
+        // a fullscreen window forward to cover another freeform activity.)
         if (mResumedActivity == next && next.isState(RESUMED)
+                && taskDisplayArea.getWindowingMode() != WINDOWING_MODE_FREEFORM
                 && taskDisplayArea.allResumedActivitiesComplete()) {
             // Make sure we have executed any pending transitions, since there
             // should be nothing left to do at this point.
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 8201d10..48550ed0 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -32,6 +32,7 @@
 import android.app.WindowConfiguration;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ParceledListSlice;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -39,6 +40,7 @@
 import android.view.SurfaceControl;
 import android.window.ITaskOrganizer;
 import android.window.ITaskOrganizerController;
+import android.window.TaskAppearedInfo;
 import android.window.WindowContainerToken;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -76,8 +78,6 @@
             WINDOWING_MODE_FREEFORM
     };
 
-    private final WindowManagerGlobalLock mGlobalLock;
-
     private class DeathRecipient implements IBinder.DeathRecipient {
         ITaskOrganizer mTaskOrganizer;
 
@@ -103,39 +103,38 @@
      * transaction before they are presented to the task org.
      */
     private class TaskOrganizerCallbacks {
-        final WindowManagerService mService;
         final ITaskOrganizer mTaskOrganizer;
         final Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
 
-        private final SurfaceControl.Transaction mTransaction;
-
-        TaskOrganizerCallbacks(WindowManagerService wm, ITaskOrganizer taskOrg,
+        TaskOrganizerCallbacks(ITaskOrganizer taskOrg,
                 Consumer<Runnable> deferTaskOrgCallbacksConsumer) {
-            mService = wm;
             mDeferTaskOrgCallbacksConsumer = deferTaskOrgCallbacksConsumer;
             mTaskOrganizer = taskOrg;
-            mTransaction = wm.mTransactionFactory.get();
         }
 
         IBinder getBinder() {
             return mTaskOrganizer.asBinder();
         }
 
+        SurfaceControl prepareLeash(Task task, boolean visible, String reason) {
+            SurfaceControl outSurfaceControl = new SurfaceControl(task.getSurfaceControl(), reason);
+            if (!task.mCreatedByOrganizer && !visible) {
+                // To prevent flashes, we hide the task prior to sending the leash to the
+                // task org if the task has previously hidden (ie. when entering PIP)
+                mTransaction.hide(outSurfaceControl);
+                mTransaction.apply();
+            }
+            return outSurfaceControl;
+        }
+
         void onTaskAppeared(Task task) {
             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task appeared taskId=%d", task.mTaskId);
             final boolean visible = task.isVisible();
             final RunningTaskInfo taskInfo = task.getTaskInfo();
             mDeferTaskOrgCallbacksConsumer.accept(() -> {
                 try {
-                    SurfaceControl outSurfaceControl = new SurfaceControl(task.getSurfaceControl(),
-                            "TaskOrganizerController.onTaskAppeared");
-                    if (!task.mCreatedByOrganizer && !visible) {
-                        // To prevent flashes, we hide the task prior to sending the leash to the
-                        // task org if the task has previously hidden (ie. when entering PIP)
-                        mTransaction.hide(outSurfaceControl);
-                        mTransaction.apply();
-                    }
-                    mTaskOrganizer.onTaskAppeared(taskInfo, outSurfaceControl);
+                    mTaskOrganizer.onTaskAppeared(taskInfo, prepareLeash(task, visible,
+                            "TaskOrganizerController.onTaskAppeared"));
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Exception sending onTaskAppeared callback", e);
                 }
@@ -208,8 +207,7 @@
                     mDeferTaskOrgCallbacksConsumer != null
                             ? mDeferTaskOrgCallbacksConsumer
                             : mService.mWindowManager.mAnimator::addAfterPrepareSurfacesRunnable;
-            mOrganizer = new TaskOrganizerCallbacks(mService.mWindowManager, organizer,
-                    deferTaskOrgCallbacksConsumer);
+            mOrganizer = new TaskOrganizerCallbacks(organizer, deferTaskOrgCallbacksConsumer);
             mDeathRecipient = new DeathRecipient(organizer);
             try {
                 organizer.asBinder().linkToDeath(mDeathRecipient, 0);
@@ -219,6 +217,18 @@
             mUid = uid;
         }
 
+        /**
+         * Register this task with this state, but doesn't trigger the task appeared callback to
+         * the organizer.
+         */
+        SurfaceControl addTaskWithoutCallback(Task t, String reason) {
+            t.mTaskAppearedSent = true;
+            if (!mOrganizedTasks.contains(t)) {
+                mOrganizedTasks.add(t);
+            }
+            return mOrganizer.prepareLeash(t, t.isVisible(), reason);
+        }
+
         void addTask(Task t) {
             if (t.mTaskAppearedSent) return;
 
@@ -265,6 +275,9 @@
         }
     }
 
+    private final ActivityTaskManagerService mService;
+    private final WindowManagerGlobalLock mGlobalLock;
+
     // List of task organizers by priority
     private final LinkedList<ITaskOrganizer> mTaskOrganizers = new LinkedList<>();
     private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
@@ -273,8 +286,7 @@
     // Set of organized tasks (by taskId) that dispatch back pressed to their organizers
     private final HashSet<Integer> mInterceptBackPressedOnRootTasks = new HashSet();
 
-    private final ActivityTaskManagerService mService;
-
+    private SurfaceControl.Transaction mTransaction;
     private RunningTaskInfo mTmpTaskInfo;
     private Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
 
@@ -299,7 +311,7 @@
      * Register a TaskOrganizer to manage tasks as they enter the a supported windowing mode.
      */
     @Override
-    public void registerTaskOrganizer(ITaskOrganizer organizer) {
+    public ParceledListSlice<TaskAppearedInfo> registerTaskOrganizer(ITaskOrganizer organizer) {
         enforceStackPermission("registerTaskOrganizer()");
         final int uid = Binder.getCallingUid();
         final long origId = Binder.clearCallingIdentity();
@@ -307,17 +319,36 @@
             synchronized (mGlobalLock) {
                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register task organizer=%s uid=%d",
                         organizer.asBinder(), uid);
+
+                // Defer initializing the transaction since the transaction factory can be set up
+                // by the tests after construction of the controller
+                if (mTransaction == null) {
+                    mTransaction = mService.mWindowManager.mTransactionFactory.get();
+                }
+
                 if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
                     mTaskOrganizers.add(organizer);
                     mTaskOrganizerStates.put(organizer.asBinder(),
                             new TaskOrganizerState(organizer, uid));
                 }
+
+                final ArrayList<TaskAppearedInfo> taskInfos = new ArrayList<>();
+                final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
                 mService.mRootWindowContainer.forAllTasks((task) -> {
                     if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, task.getWindowingMode())) {
                         return;
                     }
-                    task.updateTaskOrganizerState(true /* forceUpdate */);
+
+                    boolean returnTask = !task.mCreatedByOrganizer;
+                    task.updateTaskOrganizerState(true /* forceUpdate */,
+                            returnTask /* skipTaskAppeared */);
+                    if (returnTask) {
+                        SurfaceControl outSurfaceControl = state.addTaskWithoutCallback(task,
+                                "TaskOrganizerController.registerTaskOrganizer");
+                        taskInfos.add(new TaskAppearedInfo(task.getTaskInfo(), outSurfaceControl));
+                    }
                 });
+                return new ParceledListSlice<>(taskInfos);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 6904740..efa0525 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -122,7 +122,6 @@
 
     //tmp vars for unused relayout params
     private static final Point sTmpSurfaceSize = new Point();
-    private static final SurfaceControl sTmpSurfaceControl = new SurfaceControl();
 
     private final Window mWindow;
     private final Surface mSurface;
@@ -260,7 +259,7 @@
         try {
             session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, -1,
                     tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
-                    mTempControls, sTmpSurfaceSize, sTmpSurfaceControl);
+                    mTempControls, sTmpSurfaceSize);
         } catch (RemoteException e) {
             // Local call.
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 429cce2..4be118e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2104,8 +2104,7 @@
             int requestedWidth, int requestedHeight, int viewVisibility, int flags,
             long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
-            SurfaceControl outBLASTSurfaceControl) {
+            InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
         Arrays.fill(outActiveControls, null);
         int result = 0;
         boolean configChanged;
@@ -2280,8 +2279,7 @@
                 result = win.relayoutVisibleWindow(result, attrChanges);
 
                 try {
-                    result = createSurfaceControl(outSurfaceControl, outBLASTSurfaceControl,
-                            result, win, winAnimator);
+                    result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
                 } catch (Exception e) {
                     displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
 
@@ -2313,7 +2311,6 @@
                     // surface, let the client use that, but don't create new surface at this point.
                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface");
                     winAnimator.mSurfaceController.getSurfaceControl(outSurfaceControl);
-                    winAnimator.mSurfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl);
                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 } else {
                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
@@ -2501,8 +2498,7 @@
         return focusMayChange;
     }
 
-    private int createSurfaceControl(SurfaceControl outSurfaceControl,
-            SurfaceControl outBLASTSurfaceControl, int result,
+    private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
             WindowState win, WindowStateAnimator winAnimator) {
         if (!win.mHasSurface) {
             result |= RELAYOUT_RES_SURFACE_CHANGED;
@@ -2517,7 +2513,6 @@
         }
         if (surfaceController != null) {
             surfaceController.getSurfaceControl(outSurfaceControl);
-            surfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl);
             ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);
 
         } else {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 3b79241..25b4828 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5770,7 +5770,7 @@
     }
 
     SurfaceControl getClientViewRootSurface() {
-        return mWinAnimator.getClientViewRootSurface();
+        return mWinAnimator.getSurfaceControl();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6349e6d..972d0d4 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -359,8 +359,8 @@
             // surface before destroying it.
             if (mSurfaceController != null && mPendingDestroySurface != null) {
                 mPostDrawTransaction.reparentChildren(
-                    mSurfaceController.getClientViewRootSurface(),
-                    mPendingDestroySurface.getClientViewRootSurface()).apply();
+                    mSurfaceController.mSurfaceControl,
+                    mPendingDestroySurface.mSurfaceControl).apply();
             }
             destroySurfaceLocked();
             mSurfaceDestroyDeferred = true;
@@ -371,7 +371,7 @@
             // Our SurfaceControl is always at layer 0 within the parent Surface managed by
             // window-state. We want this old Surface to stay on top of the new one
             // until we do the swap, so we place it at a positive layer.
-            t.setLayer(mSurfaceController.getClientViewRootSurface(), PRESERVED_SURFACE_LAYER);
+            t.setLayer(mSurfaceController.mSurfaceControl, PRESERVED_SURFACE_LAYER);
         }
         mDestroyPreservedSurfaceUponRedraw = true;
         mSurfaceDestroyDeferred = true;
@@ -393,8 +393,8 @@
                 && !mPendingDestroySurface.mChildrenDetached
                 && (mWin.mActivityRecord == null || !mWin.mActivityRecord.isRelaunching())) {
             mPostDrawTransaction.reparentChildren(
-                    mPendingDestroySurface.getClientViewRootSurface(),
-                    mSurfaceController.getClientViewRootSurface()).apply();
+                    mPendingDestroySurface.mSurfaceControl,
+                    mSurfaceController.mSurfaceControl).apply();
         }
 
         destroyDeferredSurfaceLocked();
@@ -984,8 +984,8 @@
             // Instead let the children get removed when the old surface is deleted.
             if (!mPendingDestroySurface.mChildrenDetached) {
                 mPostDrawTransaction.reparentChildren(
-                        mPendingDestroySurface.getClientViewRootSurface(),
-                        mSurfaceController.getClientViewRootSurface());
+                        mPendingDestroySurface.mSurfaceControl,
+                        mSurfaceController.mSurfaceControl);
             }
         }
 
@@ -1201,10 +1201,10 @@
         mOffsetPositionForStackResize = offsetPositionForStackResize;
     }
 
-    SurfaceControl getClientViewRootSurface() {
+    SurfaceControl getSurfaceControl() {
         if (!hasSurface()) {
             return null;
         }
-        return mSurfaceController.getClientViewRootSurface();
+        return mSurfaceController.mSurfaceControl;
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index d2c36e2..feecda7 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -50,11 +50,6 @@
 
     SurfaceControl mSurfaceControl;
 
-    /**
-     * WM only uses for deferred transactions.
-     */
-    SurfaceControl mBLASTSurfaceControl;
-
     // Should only be set from within setShown().
     private boolean mSurfaceShown = false;
     private float mSurfaceX = 0;
@@ -112,22 +107,13 @@
 
         final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags &
                 WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0);
+
         if (useBLAST) {
-            b.setContainerLayer();
+            b.setBLASTLayer();
         }
 
         mSurfaceControl = b.build();
 
-        if (useBLAST) {
-            mBLASTSurfaceControl = win.makeSurface()
-                .setParent(mSurfaceControl)
-                .setName(name + "(BLAST)")
-                .setHidden(false)
-                .setBLASTLayer()
-                .setCallsite("WindowSurfaceController")
-                .build();
-        }
-
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
@@ -172,9 +158,6 @@
         } finally {
             setShown(false);
             mSurfaceControl = null;
-            if (mBLASTSurfaceControl != null) {
-                mBLASTSurfaceControl.release();
-            }
         }
     }
 
@@ -369,12 +352,6 @@
         outSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl");
     }
 
-    void getBLASTSurfaceControl(SurfaceControl outSurfaceControl) {
-        if (mBLASTSurfaceControl != null) {
-            outSurfaceControl.copyFrom(mBLASTSurfaceControl, "WindowSurfaceController.getBLASTSurfaceControl");
-        }
-    }
-
     boolean getShown() {
         return mSurfaceShown;
     }
@@ -399,21 +376,6 @@
         return mSurfaceH;
     }
 
-    /**
-     * Returns the Surface which the client-framework ViewRootImpl will be using.
-     * This is either the WSA SurfaceControl or it's BLAST child surface.
-     * This has too main uses:
-     * 1. This is the Surface the client will add children to, we use this to make
-     *    sure we don't reparent the BLAST surface itself when calling reparentChildren
-     * 2. We use this as the barrier Surface for some deferTransaction operations.
-     */
-    SurfaceControl getClientViewRootSurface() {
-        if (mBLASTSurfaceControl != null) {
-            return mBLASTSurfaceControl;
-        }
-        return mSurfaceControl;
-    }
-
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         proto.write(SHOWN, mSurfaceShown);
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
index 31ec4a5..3aedd3c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
@@ -710,7 +710,6 @@
     @Test
     public void testProviderRequest() {
         assertThat(mProvider.getRequest().isActive()).isFalse();
-        assertThat(mProvider.getRequest().getLocationRequests()).isEmpty();
 
         ILocationListener listener1 = createMockLocationListener();
         LocationRequest request1 = new LocationRequest.Builder(5).setWorkSource(
@@ -718,7 +717,6 @@
         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
 
         assertThat(mProvider.getRequest().isActive()).isTrue();
-        assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request1);
         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
         assertThat(mProvider.getRequest().isLowPower()).isFalse();
@@ -732,8 +730,6 @@
         mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
 
         assertThat(mProvider.getRequest().isActive()).isTrue();
-        assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request1,
-                request2);
         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
         assertThat(mProvider.getRequest().isLowPower()).isFalse();
@@ -742,7 +738,6 @@
         mManager.unregisterLocationRequest(listener1);
 
         assertThat(mProvider.getRequest().isActive()).isTrue();
-        assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request2);
         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
         assertThat(mProvider.getRequest().isLowPower()).isTrue();
@@ -751,7 +746,6 @@
         mManager.unregisterLocationRequest(listener2);
 
         assertThat(mProvider.getRequest().isActive()).isFalse();
-        assertThat(mProvider.getRequest().getLocationRequests()).isEmpty();
     }
 
     @Test
@@ -855,7 +849,6 @@
         mInjector.getSettingsHelper().setLocationEnabled(false, IDENTITY.getUserId());
 
         assertThat(mProvider.getRequest().isActive()).isTrue();
-        assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request2);
         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isTrue();
     }
diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
index c91bb93..9a2ce3c 100644
--- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
@@ -223,6 +223,25 @@
     }
 
     @Test
+    public void testInterceptPowerKeyDown_firstPowerDown_panicGestureNotLaunched() {
+        withPanicGestureEnabledSettingValue(true);
+        mGestureLauncherService.updatePanicButtonGestureEnabled();
+
+        long eventTime = INITIAL_EVENT_TIME_MILLIS
+                + GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS - 1;
+        KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
+                IGNORED_REPEAT);
+        boolean interactive = true;
+        MutableBoolean outLaunched = new MutableBoolean(true);
+        boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
+                outLaunched);
+
+        assertFalse(intercepted);
+        assertFalse(outLaunched.value);
+        verify(mMetricsLogger).histogram("power_double_tap_interval", (int) eventTime);
+    }
+
+    @Test
     public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive() {
         withCameraDoubleTapPowerEnableConfigValue(false);
         withCameraDoubleTapPowerDisableSettingValue(1);
@@ -405,6 +424,146 @@
     }
 
     @Test
+    public void
+            testInterceptPowerKeyDown_fiveInboundPresses_cameraAndPanicEnabled_bothLaunch() {
+        withCameraDoubleTapPowerEnableConfigValue(true);
+        withCameraDoubleTapPowerDisableSettingValue(0);
+        withPanicGestureEnabledSettingValue(true);
+        mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
+        mGestureLauncherService.updatePanicButtonGestureEnabled();
+        withUserSetupCompleteValue(true);
+
+        // First button press does nothing
+        long eventTime = INITIAL_EVENT_TIME_MILLIS;
+        KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
+                IGNORED_REPEAT);
+        boolean interactive = true;
+        MutableBoolean outLaunched = new MutableBoolean(true);
+        boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
+                outLaunched);
+        assertFalse(intercepted);
+        assertFalse(outLaunched.value);
+
+        final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
+
+        // 2nd button triggers camera
+        eventTime += interval;
+        keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
+                IGNORED_REPEAT);
+        outLaunched.value = false;
+        intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
+                outLaunched);
+        assertTrue(intercepted);
+        assertTrue(outLaunched.value);
+
+        // Camera checks
+        verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected(
+                StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
+        verify(mMetricsLogger)
+            .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval);
+
+        final ArgumentCaptor<Integer> cameraIntervalCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMetricsLogger, times(2)).histogram(
+                eq("power_double_tap_interval"), cameraIntervalCaptor.capture());
+        List<Integer> cameraIntervals = cameraIntervalCaptor.getAllValues();
+        assertEquals((int) INITIAL_EVENT_TIME_MILLIS, cameraIntervals.get(0).intValue());
+        assertEquals((int) interval, cameraIntervals.get(1).intValue());
+
+        final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMetricsLogger, times(2)).histogram(
+                eq("power_consecutive_short_tap_count"), tapCountCaptor.capture());
+        List<Integer> tapCounts = tapCountCaptor.getAllValues();
+        assertEquals(1, tapCounts.get(0).intValue());
+        assertEquals(2, tapCounts.get(1).intValue());
+
+        // Continue the button presses for the panic gesture.
+
+        // Presses 3 and 4 should not trigger any gesture
+        for (int i = 0; i < 2; i++) {
+            eventTime += interval;
+            keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
+                    IGNORED_REPEAT);
+            outLaunched.value = false;
+            intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
+                    outLaunched);
+            assertFalse(intercepted);
+            assertFalse(outLaunched.value);
+        }
+
+        // Fifth button press should trigger the panic flow
+        eventTime += interval;
+        keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
+                IGNORED_REPEAT);
+        outLaunched.value = false;
+        intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
+                outLaunched);
+        assertTrue(intercepted);
+        assertTrue(outLaunched.value);
+
+        // TODO (b/169960245) Verify metric event equiv. to ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE
+        verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected();
+
+        final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMetricsLogger, times(5)).histogram(
+                eq("power_double_tap_interval"), intervalCaptor.capture());
+        List<Integer> intervals = intervalCaptor.getAllValues();
+        assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
+        assertEquals((int) interval, intervals.get(1).intValue());
+    }
+
+    @Test
+    public void
+            testInterceptPowerKeyDown_fiveInboundPresses_panicGestureEnabled_launchesPanicFlow() {
+        withPanicGestureEnabledSettingValue(true);
+        mGestureLauncherService.updatePanicButtonGestureEnabled();
+        withUserSetupCompleteValue(true);
+
+        // First button press does nothing
+        long eventTime = INITIAL_EVENT_TIME_MILLIS;
+        KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
+                IGNORED_REPEAT);
+        boolean interactive = true;
+        MutableBoolean outLaunched = new MutableBoolean(true);
+        boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
+                outLaunched);
+        assertFalse(intercepted);
+        assertFalse(outLaunched.value);
+
+        final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
+        // 3 more button presses which should not trigger any gesture (camera gesture disabled)
+        for (int i = 0; i < 3; i++) {
+            eventTime += interval;
+            keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
+                    IGNORED_REPEAT);
+            outLaunched.value = false;
+            intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
+                    outLaunched);
+            assertFalse(intercepted);
+            assertFalse(outLaunched.value);
+        }
+
+        // Fifth button press should trigger the panic flow
+        eventTime += interval;
+        keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
+                IGNORED_REPEAT);
+        outLaunched.value = false;
+        intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
+                outLaunched);
+        assertTrue(outLaunched.value);
+        assertTrue(intercepted);
+
+        // TODO (b/169960245) Verify metric event equiv. to ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE
+        verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected();
+
+        final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mMetricsLogger, times(5)).histogram(
+                eq("power_double_tap_interval"), intervalCaptor.capture());
+        List<Integer> intervals = intervalCaptor.getAllValues();
+        assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue());
+        assertEquals((int) interval, intervals.get(1).intValue());
+    }
+
+    @Test
     public void testInterceptPowerKeyDown_longpress() {
         withCameraDoubleTapPowerEnableConfigValue(true);
         withCameraDoubleTapPowerDisableSettingValue(0);
diff --git a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
index 62e135b..c4c2f68 100644
--- a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
@@ -146,7 +146,7 @@
         // Test that package is now unstartable
         assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
         assertFalse(mIncrementalStates.isStartable());
-        assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
+        assertEquals(PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR,
                 mUnstartableReason.get());
     }
 
@@ -160,7 +160,7 @@
         // Test that package is now unstartable
         assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
         assertFalse(mIncrementalStates.isStartable());
-        assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
+        assertEquals(PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR,
                 mUnstartableReason.get());
     }
 
@@ -181,7 +181,7 @@
         // Test that package is now unstartable
         assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
         assertFalse(mIncrementalStates.isStartable());
-        assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE,
+        assertEquals(PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE,
                 mUnstartableReason.get());
     }
 
@@ -202,7 +202,7 @@
         // Test that package is now unstartable
         assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
         assertFalse(mIncrementalStates.isStartable());
-        assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE,
+        assertEquals(PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE,
                 mUnstartableReason.get());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 45534dd..aac8397 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -54,12 +54,14 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.atLeastOnce;
 
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityTaskManager.RootTaskInfo;
 import android.app.PictureInPictureParams;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ParceledListSlice;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
@@ -72,6 +74,7 @@
 import android.view.SurfaceControl;
 import android.window.ITaskOrganizer;
 import android.window.IWindowContainerTransactionCallback;
+import android.window.TaskAppearedInfo;
 import android.window.WindowContainerTransaction;
 
 import androidx.test.filters.SmallTest;
@@ -79,8 +82,10 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 
 /**
@@ -93,14 +98,27 @@
 @Presubmit
 @RunWith(WindowTestRunner.class)
 public class WindowOrganizerTests extends WindowTestsBase {
-    private ITaskOrganizer registerMockOrganizer() {
+
+    private ITaskOrganizer createMockOrganizer() {
         final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
         when(organizer.asBinder()).thenReturn(new Binder());
-
-        mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(organizer);
         return organizer;
     }
 
+    private ITaskOrganizer registerMockOrganizer(ArrayList<TaskAppearedInfo> existingTasks) {
+        final ITaskOrganizer organizer = createMockOrganizer();
+        ParceledListSlice<TaskAppearedInfo> tasks =
+                mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(organizer);
+        if (existingTasks != null) {
+            existingTasks.addAll(tasks.getList());
+        }
+        return organizer;
+    }
+
+    private ITaskOrganizer registerMockOrganizer() {
+        return registerMockOrganizer(null);
+    }
+
     Task createTask(Task stack, boolean fakeDraw) {
         final Task task = createTaskInStack(stack, 0);
 
@@ -128,27 +146,21 @@
 
     @Test
     public void testAppearVanish() throws RemoteException {
+        final ITaskOrganizer organizer = registerMockOrganizer();
         final Task stack = createStack();
         final Task task = createTask(stack);
-        final ITaskOrganizer organizer = registerMockOrganizer();
 
-        stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
-        stack.setTaskOrganizer(organizer);
         verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
 
-
         stack.removeImmediately();
         verify(organizer).onTaskVanished(any());
     }
 
     @Test
     public void testAppearWaitsForVisibility() throws RemoteException {
+        final ITaskOrganizer organizer = registerMockOrganizer();
         final Task stack = createStack();
         final Task task = createTask(stack, false);
-        final ITaskOrganizer organizer = registerMockOrganizer();
-
-        stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
-        stack.setTaskOrganizer(organizer);
 
         verify(organizer, never())
                 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
@@ -163,9 +175,9 @@
 
     @Test
     public void testNoVanishedIfNoAppear() throws RemoteException {
+        final ITaskOrganizer organizer = registerMockOrganizer();
         final Task stack = createStack();
         final Task task = createTask(stack, false /* hasBeenVisible */);
-        final ITaskOrganizer organizer = registerMockOrganizer();
 
         // In this test we skip making the Task visible, and verify
         // that even though a TaskOrganizer is set remove doesn't emit
@@ -179,28 +191,25 @@
 
     @Test
     public void testTaskNoDraw() throws RemoteException {
+        final ITaskOrganizer organizer = registerMockOrganizer();
         final Task stack = createStack();
         final Task task = createTask(stack, false /* fakeDraw */);
-        final ITaskOrganizer organizer = registerMockOrganizer();
 
-        stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         verify(organizer, never())
                 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
         assertTrue(stack.isOrganized());
 
         mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer);
-        verify(organizer, never()).onTaskVanished(any());
+        assertTaskVanished(organizer, false /* expectVanished */, stack);
         assertFalse(stack.isOrganized());
     }
 
     @Test
     public void testClearOrganizer() throws RemoteException {
+        final ITaskOrganizer organizer = registerMockOrganizer();
         final Task stack = createStack();
         final Task task = createTask(stack);
-        final ITaskOrganizer organizer = registerMockOrganizer();
 
-        stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
-        stack.setTaskOrganizer(organizer);
         verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
         assertTrue(stack.isOrganized());
 
@@ -211,16 +220,15 @@
 
     @Test
     public void testUnregisterOrganizer() throws RemoteException {
+        final ITaskOrganizer organizer = registerMockOrganizer();
         final Task stack = createStack();
         final Task task = createTask(stack);
-        final ITaskOrganizer organizer = registerMockOrganizer();
 
-        stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
         assertTrue(stack.isOrganized());
 
         mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer);
-        verify(organizer).onTaskVanished(any());
+        assertTaskVanished(organizer, true /* expectVanished */, stack);
         assertFalse(stack.isOrganized());
     }
 
@@ -232,37 +240,47 @@
         final Task task2 = createTask(stack2);
         final Task stack3 = createStack();
         final Task task3 = createTask(stack3);
-        final ITaskOrganizer organizer = registerMockOrganizer();
+        final ArrayList<TaskAppearedInfo> existingTasks = new ArrayList<>();
+        final ITaskOrganizer organizer = registerMockOrganizer(existingTasks);
 
-        // verify that tasks are appeared on registration
-        verify(organizer, times(3))
-                .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
+        // verify that tasks are returned and taskAppeared is not called
+        assertContainsTasks(existingTasks, stack, stack2, stack3);
+        verify(organizer, times(0)).onTaskAppeared(any(RunningTaskInfo.class),
+                any(SurfaceControl.class));
+        verify(organizer, times(0)).onTaskVanished(any());
         assertTrue(stack.isOrganized());
 
-        // Now we replace the registration and1 verify the new organizer receives tasks
-        final ITaskOrganizer organizer2 = registerMockOrganizer();
-        verify(organizer2, times(3))
-                .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
+        // Now we replace the registration and verify the new organizer receives existing tasks
+        final ArrayList<TaskAppearedInfo> existingTasks2 = new ArrayList<>();
+        final ITaskOrganizer organizer2 = registerMockOrganizer(existingTasks2);
+        assertContainsTasks(existingTasks2, stack, stack2, stack3);
+        verify(organizer2, times(0)).onTaskAppeared(any(RunningTaskInfo.class),
+                any(SurfaceControl.class));
         verify(organizer2, times(0)).onTaskVanished(any());
-        // One for task
-        verify(organizer, times(3)).onTaskVanished(any());
+        // Removed tasks from the original organizer
+        assertTaskVanished(organizer, true /* expectVanished */, stack, stack2, stack3);
         assertTrue(stack2.isOrganized());
 
         // Now we unregister the second one, the first one should automatically be reregistered
         // so we verify that it's now seeing changes.
         mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer2);
-        verify(organizer, times(6))
+        verify(organizer, times(3))
                 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
-        verify(organizer2, times(3)).onTaskVanished(any());
+        assertTaskVanished(organizer2, true /* expectVanished */, stack, stack2, stack3);
     }
 
     @Test
     public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
         final Task stack = createStack();
         final Task task = createTask(stack);
+        final Task stack2 = createStack();
+        final Task task2 = createTask(stack2);
+        ArrayList<TaskAppearedInfo> existingTasks = new ArrayList<>();
+        final ITaskOrganizer organizer = registerMockOrganizer(existingTasks);
+        assertContainsTasks(existingTasks, stack, stack2);
 
-        final ITaskOrganizer organizer = registerMockOrganizer();
-        verify(organizer, times(1))
+        // Verify we don't get onTaskAppeared if we are returned the tasks
+        verify(organizer, never())
                 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
     }
 
@@ -954,9 +972,9 @@
 
     @Test
     public void testPreventDuplicateAppear() throws RemoteException {
+        final ITaskOrganizer organizer = registerMockOrganizer();
         final Task stack = createStack();
         final Task task = createTask(stack, false /* fakeDraw */);
-        final ITaskOrganizer organizer = registerMockOrganizer();
 
         stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         stack.setTaskOrganizer(organizer);
@@ -977,17 +995,14 @@
 
     @Test
     public void testInterceptBackPressedOnTaskRoot() throws RemoteException {
+        final ITaskOrganizer organizer = registerMockOrganizer();
         final Task stack = createStack();
         final Task task = createTask(stack);
         final ActivityRecord activity = createActivityRecordInTask(stack.mDisplayContent, task);
         final Task stack2 = createStack();
         final Task task2 = createTask(stack2);
         final ActivityRecord activity2 = createActivityRecordInTask(stack.mDisplayContent, task2);
-        final ITaskOrganizer organizer = registerMockOrganizer();
 
-        // Setup the task to be controlled by the MW mode organizer
-        stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
-        stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         assertTrue(stack.isOrganized());
         assertTrue(stack2.isOrganized());
 
@@ -1014,9 +1029,9 @@
 
     @Test
     public void testBLASTCallbackWithMultipleWindows() throws Exception {
+        final ITaskOrganizer organizer = registerMockOrganizer();
         final Task stackController = createStack();
         final Task task = createTask(stackController);
-        final ITaskOrganizer organizer = registerMockOrganizer();
         final WindowState w1 = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window 1");
         final WindowState w2 = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window 2");
         makeWindowVisible(w1);
@@ -1067,4 +1082,37 @@
             assertFalse(daTask.isForceHidden());
         });
     }
+
+    /**
+     * Verifies that task vanished is called for a specific task.
+     */
+    private void assertTaskVanished(ITaskOrganizer organizer, boolean expectVanished, Task... tasks)
+            throws RemoteException {
+        ArgumentCaptor<RunningTaskInfo> arg = ArgumentCaptor.forClass(RunningTaskInfo.class);
+        verify(organizer, atLeastOnce()).onTaskVanished(arg.capture());
+        List<RunningTaskInfo> taskInfos = arg.getAllValues();
+
+        HashSet<Integer> vanishedTaskIds = new HashSet<>();
+        for (int i = 0; i < taskInfos.size(); i++) {
+            vanishedTaskIds.add(taskInfos.get(i).taskId);
+        }
+        HashSet<Integer> taskIds = new HashSet<>();
+        for (int i = 0; i < tasks.length; i++) {
+            taskIds.add(tasks[i].mTaskId);
+        }
+
+        assertTrue(expectVanished
+                ? vanishedTaskIds.containsAll(taskIds)
+                : !vanishedTaskIds.removeAll(taskIds));
+    }
+
+    private void assertContainsTasks(List<TaskAppearedInfo> taskInfos, Task... expectedTasks) {
+        HashSet<Integer> taskIds = new HashSet<>();
+        for (int i = 0; i < taskInfos.size(); i++) {
+            taskIds.add(taskInfos.get(i).getTaskInfo().taskId);
+        }
+        for (int i = 0; i < expectedTasks.length; i++) {
+            assertTrue(taskIds.contains(expectedTasks[i].mTaskId));
+        }
+    }
 }
diff --git a/services/usb/java/com/android/server/usb/MtpNotificationManager.java b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
index 462ee19..39f2f29 100644
--- a/services/usb/java/com/android/server/usb/MtpNotificationManager.java
+++ b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
@@ -64,12 +64,13 @@
 
     private final Context mContext;
     private final OnOpenInAppListener mListener;
+    private final Receiver mReceiver;
 
     MtpNotificationManager(Context context, OnOpenInAppListener listener) {
         mContext = context;
         mListener = listener;
-        final Receiver receiver = new Receiver();
-        context.registerReceiver(receiver, new IntentFilter(ACTION_OPEN_IN_APPS));
+        mReceiver = new Receiver();
+        context.registerReceiver(mReceiver, new IntentFilter(ACTION_OPEN_IN_APPS));
     }
 
     void showNotification(UsbDevice device) {
@@ -154,4 +155,8 @@
     static interface OnOpenInAppListener {
         void onOpenInApp(UsbDevice device);
     }
+
+    public void unregister() {
+        mContext.unregisterReceiver(mReceiver);
+    }
 }
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index d7b6b5d..26ee03c 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -261,6 +261,15 @@
     }
 
     /**
+     * Unregister all broadcast receivers. Must be called explicitly before
+     * object deletion.
+     */
+    public void unregisterReceivers() {
+        mPackageMonitor.unregister();
+        mMtpNotificationManager.unregister();
+    }
+
+    /**
      * Remove all defaults and denied packages for a user.
      *
      * @param userToRemove The user
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 7b677ee..8e53ff4 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -124,6 +124,7 @@
             if (mSettingsByProfileGroup.indexOfKey(userToRemove.getIdentifier()) >= 0) {
                 // The user to remove is the parent user of the group. The parent is the last user
                 // that gets removed. All state will be removed with the user
+                mSettingsByProfileGroup.get(userToRemove.getIdentifier()).unregisterReceivers();
                 mSettingsByProfileGroup.remove(userToRemove.getIdentifier());
             } else {
                 // We cannot find the parent user of the user that is removed, hence try to remove
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index 4fb7302..a67273c 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -227,6 +227,25 @@
     field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
   }
 
+  public final class ModemActivityInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo);
+    method public long getIdleTimeMillis();
+    method public static int getNumTxPowerLevels();
+    method public long getReceiveTimeMillis();
+    method public long getSleepTimeMillis();
+    method public long getTimestampMillis();
+    method public long getTransmitDurationMillisAtPowerLevel(int);
+    method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
+    field public static final int TX_POWER_LEVEL_0 = 0; // 0x0
+    field public static final int TX_POWER_LEVEL_1 = 1; // 0x1
+    field public static final int TX_POWER_LEVEL_2 = 2; // 0x2
+    field public static final int TX_POWER_LEVEL_3 = 3; // 0x3
+    field public static final int TX_POWER_LEVEL_4 = 4; // 0x4
+  }
+
   public final class NetworkRegistrationInfo implements android.os.Parcelable {
     method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
     method public int getRegistrationState();
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
index 2e7bde3..e089657 100644
--- a/telephony/java/android/telephony/CellSignalStrength.java
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -17,6 +17,7 @@
 package android.telephony;
 
 import android.annotation.IntRange;
+import android.annotation.SystemApi;
 import android.os.PersistableBundle;
 
 /**
@@ -155,11 +156,12 @@
 
     /**
      * Returns the number of signal strength levels.
-     * @return Number of signal strength levels, enforced to be 5
+     * @return Number of signal strength levels, currently defined in the HAL as 5.
      *
      * @hide
      */
-    public static final int getNumSignalStrengthLevels() {
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public static int getNumSignalStrengthLevels() {
         return NUM_SIGNAL_STRENGTH_BINS;
     }
 }
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index debb119..881d85c 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -16,8 +16,12 @@
 
 package android.telephony;
 
+import android.annotation.DurationMillisLong;
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -25,46 +29,50 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Arrays;
+import java.util.Objects;
 
 /**
- * Reports modem activity information.
+ * Contains information about the modem's activity. May be useful for power stats reporting.
  * @hide
  */
+@SystemApi
+@TestApi
 public final class ModemActivityInfo implements Parcelable {
+    private static final int TX_POWER_LEVELS = 5;
+
     /**
-     * Tx(transmit) power level. see power index below
-     * <ul>
-     *   <li> index 0 = tx_power < 0dBm. </li>
-     *   <li> index 1 = 0dBm < tx_power < 5dBm. </li>
-     *   <li> index 2 = 5dBm < tx_power < 15dBm. </li>
-     *   <li> index 3 = 15dBm < tx_power < 20dBm. </li>
-     *   <li> index 4 = tx_power > 20dBm. </li>
-     * </ul>
-     */
-    public static final int TX_POWER_LEVELS = 5;
-    /**
-     * Tx(transmit) power level 0: tx_power < 0dBm
+     * Corresponds to transmit power of less than 0dBm.
      */
     public static final int TX_POWER_LEVEL_0 = 0;
+
     /**
-     * Tx(transmit) power level 1: 0dBm < tx_power < 5dBm
+     * Corresponds to transmit power between 0dBm and 5dBm.
      */
     public static final int TX_POWER_LEVEL_1 = 1;
+
     /**
-     * Tx(transmit) power level 2: 5dBm < tx_power < 15dBm
+     * Corresponds to transmit power between 5dBm and 15dBm.
      */
     public static final int TX_POWER_LEVEL_2 = 2;
+
     /**
-     * Tx(transmit) power level 3: 15dBm < tx_power < 20dBm.
+     * Corresponds to transmit power between 15dBm and 20dBm.
      */
     public static final int TX_POWER_LEVEL_3 = 3;
+
     /**
-     * Tx(transmit) power level 4: tx_power > 20dBm
+     * Corresponds to transmit power above 20dBm.
      */
     public static final int TX_POWER_LEVEL_4 = 4;
 
+    /**
+     * The number of transmit power levels. Fixed by HAL definition.
+     */
+    public static int getNumTxPowerLevels() {
+        return TX_POWER_LEVELS;
+    }
+
     /** @hide */
     @IntDef(prefix = {"TX_POWER_LEVEL_"}, value = {
             TX_POWER_LEVEL_0,
@@ -82,34 +90,39 @@
         new Range<>(5, 15),
         new Range<>(15, 20),
         new Range<>(20, Integer.MAX_VALUE)
-
     };
 
     private long mTimestamp;
     private int mSleepTimeMs;
     private int mIdleTimeMs;
-    private List<TransmitPower> mTransmitPowerInfo = new ArrayList<>(TX_POWER_LEVELS);
+    private int[] mTxTimeMs;
     private int mRxTimeMs;
 
+    /**
+     * @hide
+     */
+    @TestApi
     public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
                         @NonNull int[] txTimeMs, int rxTimeMs) {
+        Objects.requireNonNull(txTimeMs);
+        if (txTimeMs.length != TX_POWER_LEVELS) {
+            throw new IllegalArgumentException("txTimeMs must have length == TX_POWER_LEVELS");
+        }
         mTimestamp = timestamp;
         mSleepTimeMs = sleepTimeMs;
         mIdleTimeMs = idleTimeMs;
-        populateTransmitPowerRange(txTimeMs);
+        mTxTimeMs = txTimeMs;
         mRxTimeMs = rxTimeMs;
     }
 
-    /** helper API to populate tx power range for each bucket **/
-    private void populateTransmitPowerRange(@NonNull int[] transmitPowerMs) {
-        int i = 0;
-        for ( ; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) {
-            mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], transmitPowerMs[i]));
-        }
-        // Make sure that mTransmitPowerInfo is fully initialized.
-        for ( ; i < TX_POWER_LEVELS; i++) {
-            mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], 0));
-        }
+    /**
+     * Provided for convenience in manipulation since the API exposes long values but internal
+     * representations are ints.
+     * @hide
+     */
+    public ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs,
+            @NonNull int[] txTimeMs, long rxTimeMs) {
+        this(timestamp, (int) sleepTimeMs, (int) idleTimeMs, txTimeMs, (int) rxTimeMs);
     }
 
     @Override
@@ -118,7 +131,7 @@
             + " mTimestamp=" + mTimestamp
             + " mSleepTimeMs=" + mSleepTimeMs
             + " mIdleTimeMs=" + mIdleTimeMs
-            + " mTransmitPowerInfo[]=" + mTransmitPowerInfo.toString()
+            + " mTxTimeMs[]=" + mTxTimeMs
             + " mRxTimeMs=" + mRxTimeMs
             + "}";
     }
@@ -129,14 +142,12 @@
 
     public static final @android.annotation.NonNull Parcelable.Creator<ModemActivityInfo> CREATOR =
             new Parcelable.Creator<ModemActivityInfo>() {
-        public ModemActivityInfo createFromParcel(Parcel in) {
+        public ModemActivityInfo createFromParcel(@NonNull Parcel in) {
             long timestamp = in.readLong();
             int sleepTimeMs = in.readInt();
             int idleTimeMs = in.readInt();
             int[] txTimeMs = new int[TX_POWER_LEVELS];
-            for (int i = 0; i < TX_POWER_LEVELS; i++) {
-                txTimeMs[i] = in.readInt();
-            }
+            in.readIntArray(txTimeMs);
             int rxTimeMs = in.readInt();
             return new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs,
                                 txTimeMs, rxTimeMs);
@@ -147,21 +158,25 @@
         }
     };
 
-    public void writeToParcel(Parcel dest, int flags) {
+    /**
+     * @param dest The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written.
+     */
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeLong(mTimestamp);
         dest.writeInt(mSleepTimeMs);
         dest.writeInt(mIdleTimeMs);
-        for (int i = 0; i < TX_POWER_LEVELS; i++) {
-            dest.writeInt(mTransmitPowerInfo.get(i).getTimeInMillis());
-        }
+        dest.writeIntArray(mTxTimeMs);
         dest.writeInt(mRxTimeMs);
     }
 
     /**
-     * @return milliseconds since boot, including mTimeInMillis spent in sleep.
-     * @see SystemClock#elapsedRealtime()
+     * Gets the timestamp at which this modem activity info was recorded.
+     *
+     * @return The timestamp, as returned by {@link SystemClock#elapsedRealtime()}, when this
+     * {@link ModemActivityInfo} was recorded.
      */
-    public long getTimestamp() {
+    public @ElapsedRealtimeLong long getTimestampMillis() {
         return mTimestamp;
     }
 
@@ -171,35 +186,48 @@
     }
 
     /**
-     * @return an arrayList of {@link TransmitPower} with each element representing the total time where
-     * transmitter is awake time (in ms) for a given power range (in dbm).
+     * Gets the amount of time the modem spent transmitting at a certain power level.
      *
-     * @see #TX_POWER_LEVELS
+     * @param powerLevel The power level to query.
+     * @return The amount of time, in milliseconds, that the modem spent transmitting at the
+     * given power level.
      */
-    @NonNull
-    public List<TransmitPower> getTransmitPowerInfo() {
-        return mTransmitPowerInfo;
+    public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel(
+            @TxPowerLevel int powerLevel) {
+        return mTxTimeMs[powerLevel];
+    }
+
+    /**
+     * Gets the range of transmit powers corresponding to a certain power level.
+     *
+     * @param powerLevel The power level to query
+     * @return A {@link Range} object representing the range of intensities (in dBm) to which this
+     * power level corresponds.
+     */
+    public @NonNull Range<Integer> getTransmitPowerRange(@TxPowerLevel int powerLevel) {
+        return TX_POWER_RANGES[powerLevel];
     }
 
     /** @hide */
     public void setTransmitTimeMillis(int[] txTimeMs) {
-        populateTransmitPowerRange(txTimeMs);
-    }
-
-    /** @hide */
-    @NonNull
-    public int[] getTransmitTimeMillis() {
-        int[] transmitTimeMillis = new int[TX_POWER_LEVELS];
-        for (int i = 0; i < transmitTimeMillis.length; i++) {
-            transmitTimeMillis[i] = mTransmitPowerInfo.get(i).getTimeInMillis();
-        }
-        return transmitTimeMillis;
+        mTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS);
     }
 
     /**
-     * @return total mTimeInMillis (in ms) when modem is in a low power or sleep state.
+     * @return The raw array of transmit power durations
+     * @hide
      */
-    public int getSleepTimeMillis() {
+    @NonNull
+    public int[] getTransmitTimeMillis() {
+        return mTxTimeMs;
+    }
+
+    /**
+     * Gets the amount of time (in milliseconds) when the modem is in a low power or sleep state.
+     *
+     * @return Time in milliseconds.
+     */
+    public @DurationMillisLong long getSleepTimeMillis() {
         return mSleepTimeMs;
     }
 
@@ -209,10 +237,44 @@
     }
 
     /**
-     * @return total mTimeInMillis (in ms) when modem is awake but neither the transmitter nor receiver are
-     * active.
+     * Provided for convenience, since the API surface needs to return longs but internal
+     * representations are ints.
+     * @hide
      */
-    public int getIdleTimeMillis() {
+    public void setSleepTimeMillis(long sleepTimeMillis) {
+        mSleepTimeMs = (int) sleepTimeMillis;
+    }
+
+    /**
+     * Computes the difference between this instance of {@link ModemActivityInfo} and another
+     * instance.
+     *
+     * This method should be used to compute the amount of activity that has happened between two
+     * samples of modem activity taken at separate times. The sample passed in as an argument to
+     * this method should be the one that's taken later in time (and therefore has more activity).
+     * @param other The other instance of {@link ModemActivityInfo} to diff against.
+     * @return An instance of {@link ModemActivityInfo} representing the difference in modem
+     * activity.
+     */
+    public @NonNull ModemActivityInfo getDelta(@NonNull ModemActivityInfo other) {
+        int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
+        for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
+            txTimeMs[i] = other.mTxTimeMs[i] - mTxTimeMs[i];
+        }
+        return new ModemActivityInfo(other.getTimestampMillis(),
+                other.getSleepTimeMillis() - getSleepTimeMillis(),
+                other.getIdleTimeMillis() - getIdleTimeMillis(),
+                txTimeMs,
+                other.getReceiveTimeMillis() - getReceiveTimeMillis());
+    }
+
+    /**
+     * Gets the amount of time (in milliseconds) when the modem is awake but neither transmitting
+     * nor receiving.
+     *
+     * @return Time in milliseconds.
+     */
+    public @DurationMillisLong long getIdleTimeMillis() {
         return mIdleTimeMs;
     }
 
@@ -222,9 +284,20 @@
     }
 
     /**
-     * @return rx(receive) mTimeInMillis in ms.
+     * Provided for convenience, since the API surface needs to return longs but internal
+     * representations are ints.
+     * @hide
      */
-    public int getReceiveTimeMillis() {
+    public void setIdleTimeMillis(long idleTimeMillis) {
+        mIdleTimeMs = (int) idleTimeMillis;
+    }
+
+    /**
+     * Gets the amount of time (in milliseconds) when the modem is awake and receiving data.
+     *
+     * @return Time in milliseconds.
+     */
+    public @DurationMillisLong long getReceiveTimeMillis() {
         return mRxTimeMs;
     }
 
@@ -234,71 +307,56 @@
     }
 
     /**
+     * Provided for convenience, since the API surface needs to return longs but internal
+     * representations are ints.
+     * @hide
+     */
+    public void setReceiveTimeMillis(long receiveTimeMillis) {
+        mRxTimeMs = (int) receiveTimeMillis;
+    }
+
+    /**
      * Indicates if the modem has reported valid {@link ModemActivityInfo}.
      *
      * @return {@code true} if this {@link ModemActivityInfo} record is valid,
      * {@code false} otherwise.
+     *  TODO: remove usages of this outside Telephony by always returning a valid (or null) result
+     *  from telephony.
+     * @hide
      */
+    @TestApi
     public boolean isValid() {
-        for (TransmitPower powerInfo : getTransmitPowerInfo()) {
-            if(powerInfo.getTimeInMillis() < 0) {
-                return false;
-            }
-        }
+        boolean isTxPowerValid = Arrays.stream(mTxTimeMs).allMatch((i) -> i >= 0);
 
-        return ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0)
+        return isTxPowerValid && ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0)
                 && (getReceiveTimeMillis() >= 0) && !isEmpty());
     }
 
     private boolean isEmpty() {
-        for (TransmitPower txVal : getTransmitPowerInfo()) {
-            if(txVal.getTimeInMillis() != 0) {
-                return false;
-            }
-        }
+        boolean isTxPowerEmpty = mTxTimeMs == null || mTxTimeMs.length == 0
+                || Arrays.stream(mTxTimeMs).allMatch((i) -> i == 0);
 
-        return ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0)
+        return isTxPowerEmpty && ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0)
                 && (getReceiveTimeMillis() == 0));
     }
 
-    /**
-     * Transmit power Information, including the power range in dbm and the total time (in ms) where
-     * the transmitter is active/awake for this power range.
-     * e.g, range: 0dbm(lower) ~ 5dbm(upper)
-     *      time: 5ms
-     */
-    public class TransmitPower {
-        private int mTimeInMillis;
-        private Range<Integer> mPowerRangeInDbm;
-        /** @hide */
-        public TransmitPower(@NonNull Range<Integer> range, int time) {
-            this.mTimeInMillis = time;
-            this.mPowerRangeInDbm = range;
-        }
 
-        /**
-         * @return the total time in ms where the transmitter is active/wake for this power range
-         * {@link #getPowerRangeInDbm()}.
-         */
-        public int getTimeInMillis() {
-            return mTimeInMillis;
-        }
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ModemActivityInfo that = (ModemActivityInfo) o;
+        return mTimestamp == that.mTimestamp
+                && mSleepTimeMs == that.mSleepTimeMs
+                && mIdleTimeMs == that.mIdleTimeMs
+                && mRxTimeMs == that.mRxTimeMs
+                && Arrays.equals(mTxTimeMs, that.mTxTimeMs);
+    }
 
-        /**
-         * @return the power range in dbm. e.g, range: 0dbm(lower) ~ 5dbm(upper)
-         */
-        @NonNull
-        public Range<Integer> getPowerRangeInDbm() {
-            return mPowerRangeInDbm;
-        }
-
-        @Override
-        public String toString() {
-            return "TransmitPower{"
-                + " mTimeInMillis=" + mTimeInMillis
-                + " mPowerRangeInDbm={" + mPowerRangeInDbm.getLower()
-                + "," + mPowerRangeInDbm.getUpper()
-                + "}}";
-        }
+    @Override
+    public int hashCode() {
+        int result = Objects.hash(mTimestamp, mSleepTimeMs, mIdleTimeMs, mRxTimeMs);
+        result = 31 * result + Arrays.hashCode(mTxTimeMs);
+        return result;
     }
 }
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index cab6209..d3fca3e 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2604,13 +2604,12 @@
     /**
      * Send an MMS message
      *
-     * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
-     * dialog. If this method is called on a device that has multiple active subscriptions, this
-     * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
-     * default subscription is defined, the subscription ID associated with this message will be
-     * INVALID, which will result in the operation being completed on the subscription associated
-     * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
-     * operation is performed on the correct subscription.
+     * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+     * manager on a multi-SIM device, this operation may fail sending the MMS message because no
+     * suitable default subscription could be found. In this case, if {@code sentIntent} is
+     * non-null, then the {@link PendingIntent} will be sent with an error code
+     * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the
+     * conditions where this operation may fail.
      * </p>
      *
      * @param context application context
@@ -2629,21 +2628,30 @@
         }
         MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE);
         if (m != null) {
-            m.sendMultimediaMessage(getSubscriptionId(), contentUri, locationUrl, configOverrides,
-                    sentIntent, 0L /* messageId */);
+            resolveSubscriptionForOperation(new SubscriptionResolverResult() {
+                @Override
+                public void onSuccess(int subId) {
+                    m.sendMultimediaMessage(subId, contentUri, locationUrl, configOverrides,
+                            sentIntent, 0L /* messageId */);
+                }
+
+                @Override
+                public void onFailure() {
+                    notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP);
+                }
+            });
         }
     }
 
     /**
      * Download an MMS message from carrier by a given location URL
      *
-     * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
-     * dialog. If this method is called on a device that has multiple active subscriptions, this
-     * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
-     * default subscription is defined, the subscription ID associated with this message will be
-     * INVALID, which will result in the operation being completed on the subscription associated
-     * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
-     * operation is performed on the correct subscription.
+     * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+     * manager on a multi-SIM device, this operation may fail downloading the MMS message because no
+     * suitable default subscription could be found. In this case, if {@code downloadedIntent} is
+     * non-null, then the {@link PendingIntent} will be sent with an error code
+     * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the
+     * conditions where this operation may fail.
      * </p>
      *
      * @param context application context
@@ -2666,8 +2674,18 @@
         }
         MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE);
         if (m != null) {
-            m.downloadMultimediaMessage(getSubscriptionId(), locationUrl, contentUri,
-                    configOverrides, downloadedIntent, 0L /* messageId */);
+            resolveSubscriptionForOperation(new SubscriptionResolverResult() {
+                @Override
+                public void onSuccess(int subId) {
+                    m.downloadMultimediaMessage(subId, locationUrl, contentUri, configOverrides,
+                            downloadedIntent, 0L /* messageId */);
+                }
+
+                @Override
+                public void onFailure() {
+                    notifySmsError(downloadedIntent, RESULT_NO_DEFAULT_SMS_APP);
+                }
+            });
         }
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 4f4a133..a202644 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2835,11 +2835,13 @@
     };
 
     /**
-     * Return a collection of all network types
-     * @return network types
+     * Returns an array of all valid network types.
+     *
+     * @return An integer array containing all valid network types in no particular order.
      *
      * @hide
      */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     public static @NonNull @NetworkType int[] getAllNetworkTypes() {
         return NETWORK_TYPES;
     }