Merge "Use ColorLongs in Linear-, Radial-, and Sweep-Gradient"
diff --git a/Android.bp b/Android.bp
index e19ca84..9b62b7a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -49,8 +49,6 @@
         "rs/java/**/*.java",
 
         ":framework-javastream-protos",
-        // TODO: Resolve circular library dependency and remove media1-srcs
-        ":media1-srcs",
 
         "core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl",
         "core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl",
@@ -505,7 +503,11 @@
         "media/java/android/media/session/ICallback.aidl",
         "media/java/android/media/session/IOnMediaKeyListener.aidl",
         "media/java/android/media/session/IOnVolumeKeyLongPressListener.aidl",
+        "media/java/android/media/session/ISession.aidl",
         "media/java/android/media/session/ISession2TokensListener.aidl",
+        "media/java/android/media/session/ISessionCallback.aidl",
+        "media/java/android/media/session/ISessionController.aidl",
+        "media/java/android/media/session/ISessionControllerCallback.aidl",
         "media/java/android/media/session/ISessionManager.aidl",
         "media/java/android/media/soundtrigger/ISoundTriggerDetectionService.aidl",
         "media/java/android/media/soundtrigger/ISoundTriggerDetectionServiceClient.aidl",
@@ -520,6 +522,8 @@
         "media/java/android/media/tv/ITvInputSessionCallback.aidl",
         "media/java/android/media/tv/ITvRemoteProvider.aidl",
         "media/java/android/media/tv/ITvRemoteServiceInput.aidl",
+        "media/java/android/service/media/IMediaBrowserService.aidl",
+        "media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl",
         "telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl",
         "telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl",
         "telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl",
diff --git a/api/current.txt b/api/current.txt
index ea2feb7..069fa99 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5811,6 +5811,7 @@
     method public final void setInterruptionFilter(int);
     method public void setNotificationDelegate(@NonNull String);
     method public void setNotificationPolicy(@NonNull android.app.NotificationManager.Policy);
+    method public boolean shouldHideSilentStatusBarIcons();
     method public boolean updateAutomaticZenRule(String, android.app.AutomaticZenRule);
     field public static final String ACTION_APP_BLOCK_STATE_CHANGED = "android.app.action.APP_BLOCK_STATE_CHANGED";
     field public static final String ACTION_AUTOMATIC_ZEN_RULE = "android.app.action.AUTOMATIC_ZEN_RULE";
@@ -11232,6 +11233,7 @@
 
   public class LauncherApps {
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(String, android.os.UserHandle);
+    method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllPackageInstallerSessions();
     method @Nullable public android.content.pm.LauncherApps.AppUsageLimit getAppUsageLimit(String, android.os.UserHandle);
     method public android.content.pm.ApplicationInfo getApplicationInfo(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.LauncherApps.PinItemRequest getPinItemRequest(android.content.Intent);
@@ -11248,13 +11250,16 @@
     method public void pinShortcuts(@NonNull String, @NonNull java.util.List<java.lang.String>, @NonNull android.os.UserHandle);
     method public void registerCallback(android.content.pm.LauncherApps.Callback);
     method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
+    method public void registerPackageInstallerSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.content.pm.PackageInstaller.SessionCallback);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
     method public boolean shouldHideFromSuggestions(@NonNull String, @NonNull android.os.UserHandle);
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+    method public void startPackageInstallerSessionDetailsActivity(android.content.pm.PackageInstaller.SessionInfo, android.graphics.Rect, android.os.Bundle);
     method public void startShortcut(@NonNull String, @NonNull String, @Nullable android.graphics.Rect, @Nullable android.os.Bundle, @NonNull android.os.UserHandle);
     method public void startShortcut(@NonNull android.content.pm.ShortcutInfo, @Nullable android.graphics.Rect, @Nullable android.os.Bundle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
+    method public void unregisterPackageInstallerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     field public static final String ACTION_CONFIRM_PIN_APPWIDGET = "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
     field public static final String ACTION_CONFIRM_PIN_SHORTCUT = "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
     field public static final String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
@@ -11444,6 +11449,7 @@
     method public long getSize();
     method public int getStagedSessionErrorCode();
     method public String getStagedSessionErrorMessage();
+    method public android.os.UserHandle getUser();
     method public boolean isActive();
     method public boolean isMultiPackage();
     method public boolean isSealed();
@@ -12978,7 +12984,7 @@
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int);
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(@Nullable android.database.sqlite.SQLiteDatabase.CursorFactory);
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(@Nullable android.database.DatabaseErrorHandler);
-    method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(@IntRange(from=0) long);
+    method @Deprecated @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(@IntRange(from=0) long);
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setJournalMode(@NonNull String);
     method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(@IntRange(from=0) int, @IntRange(from=0) int);
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int);
@@ -13039,7 +13045,7 @@
     method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int);
     method public void onOpen(android.database.sqlite.SQLiteDatabase);
     method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
-    method public void setIdleConnectionTimeout(@IntRange(from=0) long);
+    method @Deprecated public void setIdleConnectionTimeout(@IntRange(from=0) long);
     method public void setLookasideConfig(@IntRange(from=0) int, @IntRange(from=0) int);
     method public void setOpenParams(@NonNull android.database.sqlite.SQLiteDatabase.OpenParams);
     method public void setWriteAheadLoggingEnabled(boolean);
@@ -13551,10 +13557,12 @@
     method public static android.graphics.Bitmap createScaledBitmap(@NonNull android.graphics.Bitmap, int, int, boolean);
     method public int describeContents();
     method public void eraseColor(@ColorInt int);
+    method public void eraseColor(@ColorLong long);
     method @CheckResult public android.graphics.Bitmap extractAlpha();
     method @CheckResult public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]);
     method public int getAllocationByteCount();
     method public int getByteCount();
+    method public android.graphics.Color getColor(int, int);
     method @Nullable public android.graphics.ColorSpace getColorSpace();
     method public android.graphics.Bitmap.Config getConfig();
     method public int getDensity();
@@ -13580,6 +13588,7 @@
     method public void reconfigure(int, int, android.graphics.Bitmap.Config);
     method public void recycle();
     method public boolean sameAs(android.graphics.Bitmap);
+    method public void setColorSpace(@NonNull android.graphics.ColorSpace);
     method public void setConfig(android.graphics.Bitmap.Config);
     method public void setDensity(int);
     method public void setHasAlpha(boolean);
@@ -14383,6 +14392,7 @@
     method @Nullable public android.graphics.BlendMode getBlendMode();
     method @ColorInt public int getColor();
     method public android.graphics.ColorFilter getColorFilter();
+    method @ColorLong public long getColorLong();
     method public boolean getFillPath(android.graphics.Path, android.graphics.Path);
     method public int getFlags();
     method public String getFontFeatureSettings();
@@ -14403,6 +14413,7 @@
     method public float getRunAdvance(CharSequence, int, int, int, int, boolean, int);
     method public android.graphics.Shader getShader();
     method @ColorInt public int getShadowLayerColor();
+    method @ColorLong public long getShadowLayerColorLong();
     method public float getShadowLayerDx();
     method public float getShadowLayerDy();
     method public float getShadowLayerRadius();
@@ -14457,6 +14468,7 @@
     method public void setAntiAlias(boolean);
     method public void setBlendMode(@Nullable android.graphics.BlendMode);
     method public void setColor(@ColorInt int);
+    method public void setColor(@ColorLong long);
     method public android.graphics.ColorFilter setColorFilter(android.graphics.ColorFilter);
     method public void setDither(boolean);
     method public void setElegantTextHeight(boolean);
@@ -14473,6 +14485,7 @@
     method public android.graphics.PathEffect setPathEffect(android.graphics.PathEffect);
     method public android.graphics.Shader setShader(android.graphics.Shader);
     method public void setShadowLayer(float, float, float, @ColorInt int);
+    method public void setShadowLayer(float, float, float, @ColorLong long);
     method public void setStrikeThruText(boolean);
     method public void setStrokeCap(android.graphics.Paint.Cap);
     method public void setStrokeJoin(android.graphics.Paint.Join);
@@ -25580,6 +25593,14 @@
     field public static final int PLAYER_STATE_PAUSED = 1003; // 0x3eb
     field public static final int PLAYER_STATE_PLAYING = 1004; // 0x3ec
     field public static final int PLAYER_STATE_PREPARED = 1002; // 0x3ea
+    field public static final int PREPARE_DRM_STATUS_KEY_EXCHANGE_ERROR = 7; // 0x7
+    field public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3; // 0x3
+    field public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1; // 0x1
+    field public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2; // 0x2
+    field public static final int PREPARE_DRM_STATUS_RESOURCE_BUSY = 5; // 0x5
+    field public static final int PREPARE_DRM_STATUS_RESTORE_ERROR = 6; // 0x6
+    field public static final int PREPARE_DRM_STATUS_SUCCESS = 0; // 0x0
+    field public static final int PREPARE_DRM_STATUS_UNSUPPORTED_SCHEME = 4; // 0x4
     field public static final int SEEK_CLOSEST = 3; // 0x3
     field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
     field public static final int SEEK_NEXT_SYNC = 1; // 0x1
@@ -29266,6 +29287,7 @@
     method public android.net.VpnService.Builder setBlocking(boolean);
     method public android.net.VpnService.Builder setConfigureIntent(android.app.PendingIntent);
     method public android.net.VpnService.Builder setHttpProxy(android.net.ProxyInfo);
+    method public android.net.VpnService.Builder setMetered(boolean);
     method public android.net.VpnService.Builder setMtu(int);
     method public android.net.VpnService.Builder setSession(String);
     method public android.net.VpnService.Builder setUnderlyingNetworks(android.net.Network[]);
@@ -36535,7 +36557,7 @@
     field public static final String ACCOUNT_TYPE_LOCAL = "LOCAL";
     field public static final String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
     field public static final String ACTION_HANDLE_CUSTOM_EVENT = "android.provider.calendar.action.HANDLE_CUSTOM_EVENT";
-    field public static final String ACTION_VIEW_WORK_CALENDAR_EVENT = "android.provider.calendar.action.VIEW_WORK_CALENDAR_EVENT";
+    field public static final String ACTION_VIEW_MANAGED_PROFILE_CALENDAR_EVENT = "android.provider.calendar.action.VIEW_MANAGED_PROFILE_CALENDAR_EVENT";
     field public static final String AUTHORITY = "com.android.calendar";
     field public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
     field public static final android.net.Uri CONTENT_URI;
@@ -38495,13 +38517,13 @@
     field public static final String BUCKET_ID = "bucket_id";
     field public static final String DATE_TAKEN = "datetaken";
     field public static final String DESCRIPTION = "description";
+    field public static final String GROUP_ID = "group_id";
     field public static final String IS_PRIVATE = "isprivate";
     field @Deprecated public static final String LATITUDE = "latitude";
     field @Deprecated public static final String LONGITUDE = "longitude";
     field @Deprecated public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
     field public static final String ORIENTATION = "orientation";
     field @Deprecated public static final String PICASA_ID = "picasa_id";
-    field public static final String SECONDARY_BUCKET_ID = "secondary_bucket_id";
   }
 
   public static final class MediaStore.Images.Media implements android.provider.MediaStore.Images.ImageColumns {
@@ -38555,6 +38577,8 @@
     field public static final String IS_TRASHED = "is_trashed";
     field public static final String MIME_TYPE = "mime_type";
     field public static final String OWNER_PACKAGE_NAME = "owner_package_name";
+    field public static final String PRIMARY_DIRECTORY = "primary_directory";
+    field public static final String SECONDARY_DIRECTORY = "secondary_directory";
     field public static final String SIZE = "_size";
     field public static final String TITLE = "title";
     field public static final String WIDTH = "width";
@@ -38622,13 +38646,13 @@
     field public static final String DATE_TAKEN = "datetaken";
     field public static final String DESCRIPTION = "description";
     field public static final String DURATION = "duration";
+    field public static final String GROUP_ID = "group_id";
     field public static final String IS_PRIVATE = "isprivate";
     field public static final String LANGUAGE = "language";
     field @Deprecated public static final String LATITUDE = "latitude";
     field @Deprecated public static final String LONGITUDE = "longitude";
     field @Deprecated public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
     field public static final String RESOLUTION = "resolution";
-    field public static final String SECONDARY_BUCKET_ID = "secondary_bucket_id";
     field public static final String TAGS = "tags";
   }
 
@@ -38852,6 +38876,7 @@
     field @Deprecated public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
     field @Deprecated public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
     field @Deprecated public static final int LOCATION_MODE_OFF = 0; // 0x0
+    field @Deprecated public static final int LOCATION_MODE_ON = 3; // 0x3
     field @Deprecated public static final int LOCATION_MODE_SENSORS_ONLY = 1; // 0x1
     field @Deprecated public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
     field @Deprecated public static final String LOCK_PATTERN_ENABLED = "lock_pattern_autolock";
@@ -41563,6 +41588,7 @@
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap, int);
+    method public void onStatusBarIconsBehaviorChanged(boolean);
     method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
     method public static void requestRebind(android.content.ComponentName);
@@ -41875,10 +41901,6 @@
     method public void showSession(android.os.Bundle, int);
     field public static final String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
     field public static final String SERVICE_META_DATA = "android.voice_interaction";
-    field public static final int VOICE_STATE_CONDITIONAL_LISTENING = 1; // 0x1
-    field public static final int VOICE_STATE_FULFILLING = 3; // 0x3
-    field public static final int VOICE_STATE_LISTENING = 2; // 0x2
-    field public static final int VOICE_STATE_NONE = 0; // 0x0
   }
 
   public class VoiceInteractionSession implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback {
diff --git a/api/system-current.txt b/api/system-current.txt
index 19b3f0e..75f54f9b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -501,6 +501,13 @@
     method public org.json.JSONObject toJson() throws org.json.JSONException;
   }
 
+  public class NotificationManager {
+    method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
+    method @Nullable public android.content.ComponentName getAllowedNotificationAssistantForUser(android.os.UserHandle);
+    method public void setNotificationAssistantAccessGranted(android.content.ComponentName, boolean);
+    method public void setNotificationAssistantAccessGrantedForUser(android.content.ComponentName, android.os.UserHandle, boolean);
+  }
+
   public final class StatsManager {
     method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException;
     method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean addConfiguration(long, byte[]);
@@ -983,6 +990,7 @@
   }
 
   public static final class AppPredictionContext.Builder {
+    ctor public AppPredictionContext.Builder(@NonNull android.content.Context);
     method public android.app.prediction.AppPredictionContext build();
     method public android.app.prediction.AppPredictionContext.Builder setExtras(@Nullable android.os.Bundle);
     method public android.app.prediction.AppPredictionContext.Builder setPredictedTargetCount(int);
@@ -1014,6 +1022,8 @@
   }
 
   public final class AppTarget implements android.os.Parcelable {
+    ctor public AppTarget(@NonNull android.app.prediction.AppTargetId, @NonNull String, @Nullable String, @NonNull android.os.UserHandle);
+    ctor public AppTarget(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo, @Nullable String);
     method public int describeContents();
     method @Nullable public String getClassName();
     method @NonNull public android.app.prediction.AppTargetId getId();
@@ -1044,6 +1054,7 @@
   }
 
   public final class AppTargetId implements android.os.Parcelable {
+    ctor public AppTargetId(@NonNull String);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.prediction.AppTargetId> CREATOR;
@@ -3664,7 +3675,7 @@
   }
 
   public final class MediaSessionEngine implements java.lang.AutoCloseable {
-    ctor public MediaSessionEngine(@NonNull android.content.Context, @NonNull android.media.session.SessionLink, @NonNull android.media.session.SessionCallbackLink, @NonNull android.media.session.MediaSessionEngine.CallbackStub);
+    ctor public MediaSessionEngine(@NonNull android.content.Context, @NonNull android.media.session.SessionLink, @NonNull android.media.session.SessionCallbackLink);
     method public void close();
     method public String getCallingPackage();
     method @NonNull public android.media.session.MediaController getController();
@@ -3689,33 +3700,6 @@
     method public void setSessionActivity(@Nullable android.app.PendingIntent);
   }
 
-  public static final class MediaSessionEngine.CallbackStub {
-    ctor public MediaSessionEngine.CallbackStub();
-    method public void onAdjustVolume(String, int, int, android.media.session.ControllerCallbackLink, int);
-    method public void onCommand(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle, android.os.ResultReceiver);
-    method public void onCustomAction(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onFastForward(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onMediaButton(String, int, int, android.content.Intent, int, android.os.ResultReceiver);
-    method public void onMediaButtonFromController(String, int, int, android.media.session.ControllerCallbackLink, android.content.Intent);
-    method public void onNext(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onPause(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onPlay(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onPlayFromMediaId(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onPlayFromSearch(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onPlayFromUri(String, int, int, android.media.session.ControllerCallbackLink, android.net.Uri, android.os.Bundle);
-    method public void onPrepare(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onPrepareFromMediaId(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onPrepareFromSearch(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onPrepareFromUri(String, int, int, android.media.session.ControllerCallbackLink, android.net.Uri, android.os.Bundle);
-    method public void onPrevious(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onRate(String, int, int, android.media.session.ControllerCallbackLink, android.media.Rating);
-    method public void onRewind(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onSeekTo(String, int, int, android.media.session.ControllerCallbackLink, long);
-    method public void onSetVolumeTo(String, int, int, android.media.session.ControllerCallbackLink, int);
-    method public void onSkipToTrack(String, int, int, android.media.session.ControllerCallbackLink, long);
-    method public void onStop(String, int, int, android.media.session.ControllerCallbackLink);
-  }
-
   public static interface MediaSessionEngine.MediaButtonEventDelegate {
     method public boolean onMediaButtonIntent(android.content.Intent);
   }
@@ -4095,6 +4079,7 @@
 
   public class CaptivePortal implements android.os.Parcelable {
     ctor public CaptivePortal(android.os.IBinder);
+    method public void logEvent(int, String);
     method public void useNetwork();
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
     field public static final int APP_RETURN_UNWANTED = 1; // 0x1
@@ -5832,6 +5817,7 @@
   public static interface DeviceConfig.ActivityManager {
     field public static final String KEY_COMPACT_ACTION_1 = "compact_action_1";
     field public static final String KEY_COMPACT_ACTION_2 = "compact_action_2";
+    field public static final String KEY_COMPACT_STATSD_SAMPLE_RATE = "compact_statsd_sample_rate";
     field public static final String KEY_COMPACT_THROTTLE_1 = "compact_throttle_1";
     field public static final String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2";
     field public static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3";
@@ -5841,26 +5827,31 @@
     field public static final String NAMESPACE = "activity_manager";
   }
 
+  public static interface DeviceConfig.ActivityManagerNativeBoot {
+    field public static final String NAMESPACE = "activity_manager_native_boot";
+    field public static final String OFFLOAD_QUEUE_ENABLED = "offload_queue_enabled";
+  }
+
   public static interface DeviceConfig.AttentionManagerService {
+    field public static final String COMPONENT_NAME = "component_name";
     field public static final String NAMESPACE = "attention_manager_service";
-    field public static final String PROPERTY_COMPONENT_NAME = "component_name";
-    field public static final String PROPERTY_SERVICE_ENABLED = "service_enabled";
+    field public static final String SERVICE_ENABLED = "service_enabled";
   }
 
   public static interface DeviceConfig.ContentCapture {
     field public static final String NAMESPACE = "content_capture";
   }
 
-  public static interface DeviceConfig.FsiBoot {
-    field public static final String NAMESPACE = "fsi_boot";
-    field public static final String OOB_ENABLED = "oob_enabled";
-    field public static final String OOB_WHITELIST = "oob_whitelist";
+  public static interface DeviceConfig.DexBoot {
+    field public static final String NAMESPACE = "dex_boot";
+    field public static final String PRIV_APPS_OOB_ENABLED = "priv_apps_oob_enabled";
+    field public static final String PRIV_APPS_OOB_WHITELIST = "priv_apps_oob_whitelist";
   }
 
   public static interface DeviceConfig.IntelligenceAttention {
+    field public static final String ATTENTION_ENABLED = "attention_enabled";
+    field public static final String ATTENTION_SETTINGS = "attention_settings";
     field public static final String NAMESPACE = "intelligence_attention";
-    field public static final String PROPERTY_ATTENTION_ENABLED = "attention_enabled";
-    field public static final String PROPERTY_ATTENTION_SETTINGS = "attention_settings";
   }
 
   public static interface DeviceConfig.NotificationAssistant {
@@ -5875,8 +5866,8 @@
 
   public static interface DeviceConfig.Privacy {
     field public static final String NAMESPACE = "privacy";
-    field public static final String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED = "enable_location_access_check";
-    field public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "enable_permissions_hub";
+    field public static final String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED = "location_access_check_enabled";
+    field public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
   }
 
   public static interface DeviceConfig.RuntimeNative {
@@ -5890,8 +5881,9 @@
 
   public static interface DeviceConfig.Telephony {
     field public static final String NAMESPACE = "telephony";
-    field public static final String PROPERTY_ENABLE_RAMPING_RINGER = "enable_ramping_ringer";
-    field public static final String PROPERTY_RAMPING_RINGER_DURATION = "ramping_duration";
+    field public static final String RAMPING_RINGER_DURATION = "ramping_ringer_duration";
+    field public static final String RAMPING_RINGER_ENABLED = "ramping_ringer_enabled";
+    field public static final String RAMPING_RINGER_VIBRATION_DURATION = "ramping_ringer_vibration_duration";
   }
 
   public final class DocumentsContract {
@@ -7914,12 +7906,13 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPreferredNetworkTypeBitmap();
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getLogicalToPhysicalSlotMapping();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmap();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
     method public int getSimApplicationState();
     method public int getSimCardState();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getSimLocale();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSupportedRadioAccessFamily();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
     method @Nullable public android.os.Bundle getVisualVoicemailSettings();
@@ -7947,7 +7940,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultisimCarrierRestriction(boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmap(int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmap(long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
@@ -7972,25 +7965,26 @@
     field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
     field public static final long MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS = 60000L; // 0xea60L
-    field public static final int NETWORK_TYPE_BITMASK_1xRTT = 128; // 0x80
-    field public static final int NETWORK_TYPE_BITMASK_CDMA = 16; // 0x10
-    field public static final int NETWORK_TYPE_BITMASK_EDGE = 4; // 0x4
-    field public static final int NETWORK_TYPE_BITMASK_EHRPD = 16384; // 0x4000
-    field public static final int NETWORK_TYPE_BITMASK_EVDO_0 = 32; // 0x20
-    field public static final int NETWORK_TYPE_BITMASK_EVDO_A = 64; // 0x40
-    field public static final int NETWORK_TYPE_BITMASK_EVDO_B = 4096; // 0x1000
-    field public static final int NETWORK_TYPE_BITMASK_GPRS = 2; // 0x2
-    field public static final int NETWORK_TYPE_BITMASK_GSM = 65536; // 0x10000
-    field public static final int NETWORK_TYPE_BITMASK_HSDPA = 256; // 0x100
-    field public static final int NETWORK_TYPE_BITMASK_HSPA = 1024; // 0x400
-    field public static final int NETWORK_TYPE_BITMASK_HSPAP = 32768; // 0x8000
-    field public static final int NETWORK_TYPE_BITMASK_HSUPA = 512; // 0x200
-    field public static final int NETWORK_TYPE_BITMASK_LTE = 8192; // 0x2000
-    field public static final int NETWORK_TYPE_BITMASK_LTE_CA = 524288; // 0x80000
-    field public static final int NETWORK_TYPE_BITMASK_NR = 1048576; // 0x100000
-    field public static final int NETWORK_TYPE_BITMASK_TD_SCDMA = 131072; // 0x20000
-    field public static final int NETWORK_TYPE_BITMASK_UMTS = 8; // 0x8
-    field public static final int NETWORK_TYPE_BITMASK_UNKNOWN = 1; // 0x1
+    field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
+    field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
+    field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
+    field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L
+    field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L
+    field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L
+    field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L
+    field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L
+    field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L
+    field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L
+    field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L
+    field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L
+    field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L
+    field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L
+    field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L
+    field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L
+    field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L
+    field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
+    field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
+    field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
     field public static final int RADIO_POWER_OFF = 0; // 0x0
     field public static final int RADIO_POWER_ON = 1; // 0x1
     field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2
diff --git a/api/test-current.txt b/api/test-current.txt
index 4fc1757..2f4d455 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -242,6 +242,7 @@
 
   public class NotificationManager {
     method public android.content.ComponentName getEffectsSuppressor();
+    method public boolean matchesCallFilter(android.os.Bundle);
   }
 
   public final class PictureInPictureParams implements android.os.Parcelable {
@@ -332,6 +333,91 @@
 
 }
 
+package android.app.prediction {
+
+  public final class AppPredictionContext implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public android.os.Bundle getExtras();
+    method @NonNull public String getPackageName();
+    method public int getPredictedTargetCount();
+    method public String getUiSurface();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.prediction.AppPredictionContext> CREATOR;
+  }
+
+  public static final class AppPredictionContext.Builder {
+    ctor public AppPredictionContext.Builder(@NonNull android.content.Context);
+    method public android.app.prediction.AppPredictionContext build();
+    method public android.app.prediction.AppPredictionContext.Builder setExtras(@Nullable android.os.Bundle);
+    method public android.app.prediction.AppPredictionContext.Builder setPredictedTargetCount(int);
+    method public android.app.prediction.AppPredictionContext.Builder setUiSurface(@Nullable String);
+  }
+
+  public final class AppPredictionManager {
+    method public android.app.prediction.AppPredictor createAppPredictionSession(@NonNull android.app.prediction.AppPredictionContext);
+  }
+
+  public final class AppPredictionSessionId implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.prediction.AppPredictionSessionId> CREATOR;
+  }
+
+  public final class AppPredictor {
+    method public void destroy();
+    method public android.app.prediction.AppPredictionSessionId getSessionId();
+    method public void notifyAppTargetEvent(@NonNull android.app.prediction.AppTargetEvent);
+    method public void notifyLocationShown(@NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>);
+    method public void registerPredictionUpdates(@NonNull java.util.concurrent.Executor, @NonNull android.app.prediction.AppPredictor.Callback);
+    method public void requestPredictionUpdate();
+    method @Nullable public void sortTargets(@NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>);
+    method public void unregisterPredictionUpdates(@NonNull android.app.prediction.AppPredictor.Callback);
+  }
+
+  public static interface AppPredictor.Callback {
+    method public void onTargetsAvailable(@NonNull java.util.List<android.app.prediction.AppTarget>);
+  }
+
+  public final class AppTarget implements android.os.Parcelable {
+    ctor public AppTarget(@NonNull android.app.prediction.AppTargetId, @NonNull String, @Nullable String, @NonNull android.os.UserHandle);
+    method public int describeContents();
+    method @Nullable public String getClassName();
+    method @NonNull public android.app.prediction.AppTargetId getId();
+    method @NonNull public String getPackageName();
+    method public int getRank();
+    method @Nullable public android.content.pm.ShortcutInfo getShortcutInfo();
+    method @NonNull public android.os.UserHandle getUser();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.prediction.AppTarget> CREATOR;
+  }
+
+  public final class AppTargetEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public int getAction();
+    method @NonNull public String getLaunchLocation();
+    method @Nullable public android.app.prediction.AppTarget getTarget();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACTION_DISMISS = 2; // 0x2
+    field public static final int ACTION_LAUNCH = 1; // 0x1
+    field public static final int ACTION_PIN = 3; // 0x3
+    field public static final android.os.Parcelable.Creator<android.app.prediction.AppTargetEvent> CREATOR;
+  }
+
+  public static final class AppTargetEvent.Builder {
+    ctor public AppTargetEvent.Builder(@Nullable android.app.prediction.AppTarget, int);
+    method public android.app.prediction.AppTargetEvent build();
+    method public android.app.prediction.AppTargetEvent.Builder setLaunchLocation(String);
+  }
+
+  public final class AppTargetId implements android.os.Parcelable {
+    ctor public AppTargetId(@NonNull String);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.prediction.AppTargetId> CREATOR;
+  }
+
+}
+
 package android.app.role {
 
   public final class RoleManager {
@@ -518,23 +604,10 @@
 
 package android.graphics {
 
-  public final class Bitmap implements android.os.Parcelable {
-    method public void eraseColor(@ColorLong long);
-    method public android.graphics.Color getColor(int, int);
-    method public void setColorSpace(@NonNull android.graphics.ColorSpace);
-  }
-
   public final class ImageDecoder implements java.lang.AutoCloseable {
     method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(android.content.res.Resources, java.io.InputStream, int);
   }
 
-  public class Paint {
-    method @ColorLong public long getColorLong();
-    method @ColorLong public long getShadowLayerColorLong();
-    method public void setColor(@ColorLong long);
-    method public void setShadowLayer(float, float, float, @ColorLong long);
-  }
-
 }
 
 package android.graphics.drawable {
@@ -754,6 +827,17 @@
     method public android.media.BufferingParams.Builder setResumePlaybackMarkMs(int);
   }
 
+  public class MediaPlayer2 implements android.media.AudioRouting java.lang.AutoCloseable {
+    method public android.media.MediaPlayer2.DrmInfo getDrmInfo(@NonNull android.media.DataSourceDesc);
+    method public android.media.MediaDrm.KeyRequest getDrmKeyRequest(@NonNull android.media.DataSourceDesc, @Nullable byte[], @Nullable byte[], @Nullable String, int, @Nullable java.util.Map<java.lang.String,java.lang.String>) throws android.media.MediaPlayer2.NoDrmSchemeException;
+    method public String getDrmPropertyString(@NonNull android.media.DataSourceDesc, @NonNull String) throws android.media.MediaPlayer2.NoDrmSchemeException;
+    method public Object prepareDrm(@NonNull android.media.DataSourceDesc, @NonNull java.util.UUID);
+    method public byte[] provideDrmKeyResponse(@NonNull android.media.DataSourceDesc, @Nullable byte[], @NonNull byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer2.NoDrmSchemeException;
+    method public void releaseDrm(@NonNull android.media.DataSourceDesc) throws android.media.MediaPlayer2.NoDrmSchemeException;
+    method public void restoreDrmKeys(@NonNull android.media.DataSourceDesc, @NonNull byte[]) throws android.media.MediaPlayer2.NoDrmSchemeException;
+    method public void setDrmPropertyString(@NonNull android.media.DataSourceDesc, @NonNull String, @NonNull String) throws android.media.MediaPlayer2.NoDrmSchemeException;
+  }
+
   public final class PlaybackParams implements android.os.Parcelable {
     method public int getAudioStretchMode();
     method public android.media.PlaybackParams setAudioStretchMode(int);
@@ -804,6 +888,7 @@
 
   public class CaptivePortal implements android.os.Parcelable {
     ctor public CaptivePortal(android.os.IBinder);
+    method public void logEvent(int, String);
     method public void useNetwork();
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
     field public static final int APP_RETURN_UNWANTED = 1; // 0x1
@@ -1659,7 +1744,7 @@
 
   public static interface DeviceConfig.Privacy {
     field public static final String NAMESPACE = "privacy";
-    field public static final String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED = "enable_location_access_check";
+    field public static final String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED = "location_access_check_enabled";
   }
 
   public final class MediaStore {
@@ -1773,6 +1858,24 @@
 
 }
 
+package android.service.appprediction {
+
+  public abstract class AppPredictionService extends android.app.Service {
+    ctor public AppPredictionService();
+    method @MainThread public abstract void onAppTargetEvent(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull android.app.prediction.AppTargetEvent);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onCreatePredictionSession(@NonNull android.app.prediction.AppPredictionContext, @NonNull android.app.prediction.AppPredictionSessionId);
+    method @MainThread public void onDestroyPredictionSession(@NonNull android.app.prediction.AppPredictionSessionId);
+    method @MainThread public abstract void onLocationShown(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>);
+    method @MainThread public abstract void onRequestPredictionUpdate(@NonNull android.app.prediction.AppPredictionSessionId);
+    method @MainThread public abstract void onSortAppTargets(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>);
+    method @MainThread public void onStartPredictionUpdates();
+    method @MainThread public void onStopPredictionUpdates();
+    method public final void updatePredictions(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull java.util.List<android.app.prediction.AppTarget>);
+  }
+
+}
+
 package android.service.autofill {
 
   public abstract class AutofillFieldClassificationService extends android.app.Service {
@@ -2386,6 +2489,10 @@
     method public boolean isSystemGroup();
   }
 
+  public abstract class LayoutInflater {
+    method public void setPrecompiledLayoutsEnabledForTesting(boolean);
+  }
+
   public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
     method public void setActionButton(int);
     method public void setButtonState(int);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 30df850..427662a 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -234,6 +234,7 @@
         BluetoothBondStateChanged bluetooth_bond_state_changed = 165;
         BluetoothClassicPairingEventReported bluetooth_classic_pairing_event_reported = 166;
         BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported = 167;
+        ScreenTimeoutExtensionReported screen_timeout_extension_reported = 168;
     }
 
     // Pulled events will start at field 10000.
@@ -288,6 +289,7 @@
         DebugElapsedClock debug_elapsed_clock = 10046;
         DebugFailingElapsedClock debug_failing_elapsed_clock = 10047;
         NumBiometricsEnrolled num_faces_enrolled = 10048;
+        RoleHolder role_holder = 10049;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -3973,6 +3975,20 @@
     optional int32 num_enrolled = 2;
 }
 
+/**
+ * A mapping of role holder -> role
+ */
+message RoleHolder {
+    // uid of the role holder
+    optional int32 uid = 1 [(is_uid) = true];
+
+    // package name of the role holder
+    optional string package_name = 2;
+
+    // the role held
+    optional string role = 3;
+}
+
 message AggStats {
     optional int64 min = 1;
 
@@ -4968,17 +4984,17 @@
  *     packages/apps/Nfc/src/com/android/nfc/cardemulation/AidRoutingManager.java
  */
 message NfcErrorOccurred {
-  enum Type {
-    UNKNOWN = 0;
-    CMD_TIMEOUT = 1;
-    ERROR_NOTIFICATION = 2;
-    AID_OVERFLOW = 3;
-  }
-  optional Type type = 1;
-  // If it's nci cmd timeout, log the timeout command.
-  optional uint32 nci_cmd = 2;
+    enum Type {
+        UNKNOWN = 0;
+        CMD_TIMEOUT = 1;
+        ERROR_NOTIFICATION = 2;
+        AID_OVERFLOW = 3;
+    }
+    optional Type type = 1;
+    // If it's nci cmd timeout, log the timeout command.
+    optional uint32 nci_cmd = 2;
 
-  optional uint32 error_ntf_status_code = 3;
+    optional uint32 error_ntf_status_code = 3;
 }
 
 /**
@@ -4987,14 +5003,14 @@
  *     packages/apps/Nfc/src/com/android/nfc/NfcService.java
  */
 message NfcStateChanged {
-  enum State {
-    UNKNOWN = 0;
-    OFF = 1;
-    ON = 2;
-    ON_LOCKED = 3; // Secure Nfc enabled.
-    CRASH_RESTART = 4; // NfcService watchdog timeout restart.
-  }
-  optional State state = 1;
+    enum State {
+        UNKNOWN = 0;
+        OFF = 1;
+        ON = 2;
+        ON_LOCKED = 3; // Secure Nfc enabled.
+        CRASH_RESTART = 4; // NfcService watchdog timeout restart.
+    }
+    optional State state = 1;
 }
 
 /**
@@ -5003,12 +5019,12 @@
  *     packages/apps/Nfc/src/com/android/nfc/P2pLinkManager.java
  */
 message NfcBeamOccurred {
-  enum Operation {
-      UNKNOWN = 0;
-      SEND = 1;
-      RECEIVE = 2;
-  }
-  optional Operation operation = 1;
+    enum Operation {
+        UNKNOWN = 0;
+        SEND = 1;
+        RECEIVE = 2;
+    }
+    optional Operation operation = 1;
 }
 
 /**
@@ -5018,16 +5034,16 @@
  *     packages/apps/Nfc/src/com/android/nfc/cardemulation/HostNfcFEmulationManager.java
  */
 message NfcCardemulationOccurred {
-  enum Category {
-      UNKNOWN = 0;
-      HCE_PAYMENT = 1;
-      HCE_OTHER = 2;
-      OFFHOST = 3;
-  }
-  // Transaction belongs to HCE payment or HCE other category, or offhost.
-  optional Category category = 1;
-  // SeName from transaction: SIMx, eSEx, HCE, HCEF.
-  optional string se_name = 2;
+    enum Category {
+        UNKNOWN = 0;
+        HCE_PAYMENT = 1;
+        HCE_OTHER = 2;
+        OFFHOST = 3;
+    }
+    // Transaction belongs to HCE payment or HCE other category, or offhost.
+    optional Category category = 1;
+    // SeName from transaction: SIMx, eSEx, HCE, HCEF.
+    optional string se_name = 2;
 }
 
 /**
@@ -5036,16 +5052,16 @@
  *     packages/apps/Nfc/src/com/android/nfc/NfcDispatcher.java
  */
 message NfcTagOccurred {
-  enum Type {
-      UNKNOWN = 0;
-      URL = 1;
-      BT_PAIRING = 2;
-      PROVISION = 3;
-      WIFI_CONNECT = 4;
-      APP_LAUNCH = 5;
-      OTHERS = 6;
-  }
-  optional Type type = 1;
+    enum Type {
+        UNKNOWN = 0;
+        URL = 1;
+        BT_PAIRING = 2;
+        PROVISION = 3;
+        WIFI_CONNECT = 4;
+        APP_LAUNCH = 5;
+        OTHERS = 6;
+    }
+    optional Type type = 1;
 }
 
 /**
@@ -5065,18 +5081,18 @@
  *     packages/apps/SecureElement/src/com/android/se/Terminal.java
  */
 message SeStateChanged {
-  enum State {
-    UNKNOWN = 0;
-    INITIALIZED = 1;
-    DISCONNECTED = 2;
-    CONNECTED = 3;
-    HALCRASH = 4;
-  }
-  optional State state = 1;
+    enum State {
+        UNKNOWN = 0;
+        INITIALIZED = 1;
+        DISCONNECTED = 2;
+        CONNECTED = 3;
+        HALCRASH = 4;
+    }
+    optional State state = 1;
 
-  optional string state_change_reason = 2;
-  // SIMx or eSEx.
-  optional string terminal = 3;
+    optional string state_change_reason = 2;
+    // SIMx or eSEx.
+    optional string terminal = 3;
 }
 
 /**
@@ -5085,15 +5101,15 @@
  *     packages/apps/SecureElement/src/com/android/se/Terminal.java
  */
 message SeOmapiReported {
-  enum Operation {
-    UNKNOWN = 0;
-    OPEN_CHANNEL = 1;
-  }
-  optional Operation operation = 1;
-  // SIMx or eSEx.
-  optional string terminal = 2;
+    enum Operation {
+        UNKNOWN = 0;
+        OPEN_CHANNEL = 1;
+    }
+    optional Operation operation = 1;
+    // SIMx or eSEx.
+    optional string terminal = 2;
 
-  optional string package_name = 3;
+    optional string package_name = 3;
 }
 
 /**
@@ -5275,3 +5291,15 @@
     }
     optional State state = 4;
 }
+
+/**
+ * Logs PowerManagerService screen timeout resets (extensions) that happen when an attention check
+ * returns true.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
+ */
+message ScreenTimeoutExtensionReported {
+    // Describes how many times in a row did the power manager reset the screen off timeout.
+    optional uint32 consecutive_timeout_extended_count = 1;
+}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index a6ba2ca..6f3eeaa7 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -220,6 +220,9 @@
         // BuildInformation.
         {android::util::BUILD_INFORMATION,
          {.puller = new StatsCompanionServicePuller(android::util::BUILD_INFORMATION)}},
+        // RoleHolder.
+        {android::util::ROLE_HOLDER,
+         {.puller = new StatsCompanionServicePuller(android::util::ROLE_HOLDER)}},
 };
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 03a09ee..4a8566c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -6083,7 +6083,12 @@
             instrApp.initForUser(UserHandle.myUserId());
             final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                     appContext.getClassLoader(), false, true, false);
-            final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
+
+            // The test context's op package name == the target app's op package name, because
+            // the app ops manager checks the op package name against the real calling UID,
+            // which is what the target package name is associated with.
+            final ContextImpl instrContext = ContextImpl.createAppContext(this, pi,
+                    appContext.getOpPackageName());
 
             try {
                 final ClassLoader cl = instrContext.getClassLoader();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 92cdb20..1a728c1 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2128,7 +2128,7 @@
                 flags | CONTEXT_REGISTER_PACKAGE);
         if (pi != null) {
             ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken,
-                    new UserHandle(UserHandle.getUserId(application.uid)), flags, null);
+                    new UserHandle(UserHandle.getUserId(application.uid)), flags, null, null);
 
             final int displayId = getDisplayId();
 
@@ -2156,14 +2156,14 @@
             // The system resources are loaded in every application, so we can safely copy
             // the context without reloading Resources.
             return new ContextImpl(this, mMainThread, mPackageInfo, null, mActivityToken, user,
-                    flags, null);
+                    flags, null, null);
         }
 
         LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
                 flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
         if (pi != null) {
             ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user,
-                    flags, null);
+                    flags, null, null);
 
             final int displayId = getDisplayId();
 
@@ -2190,7 +2190,7 @@
         final String[] paths = mPackageInfo.getSplitPaths(splitName);
 
         final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, splitName,
-                mActivityToken, mUser, mFlags, classLoader);
+                mActivityToken, mUser, mFlags, classLoader, null);
 
         final int displayId = getDisplayId();
 
@@ -2214,7 +2214,7 @@
         }
 
         ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
-                mActivityToken, mUser, mFlags, mClassLoader);
+                mActivityToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = getDisplayId();
         context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
@@ -2229,7 +2229,7 @@
         }
 
         ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
-                mActivityToken, mUser, mFlags, mClassLoader);
+                mActivityToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = display.getDisplayId();
         context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
@@ -2243,7 +2243,7 @@
         final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
                 | Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
         return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
-                flags, mClassLoader);
+                flags, mClassLoader, null);
     }
 
     @Override
@@ -2251,7 +2251,7 @@
         final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
                 | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
         return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
-                flags, mClassLoader);
+                flags, mClassLoader, null);
     }
 
     @Override
@@ -2397,7 +2397,7 @@
     static ContextImpl createSystemContext(ActivityThread mainThread) {
         LoadedApk packageInfo = new LoadedApk(mainThread);
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
-                null);
+                null, null);
         context.setResources(packageInfo.getResources());
         context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                 context.mResourcesManager.getDisplayMetrics());
@@ -2414,7 +2414,7 @@
     static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
         final LoadedApk packageInfo = systemContext.mPackageInfo;
         ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
-                null, null, 0, null);
+                null, null, 0, null, null);
         context.setResources(createResources(null, packageInfo, null, displayId, null,
                 packageInfo.getCompatibilityInfo()));
         context.updateDisplay(displayId);
@@ -2431,9 +2431,14 @@
 
     @UnsupportedAppUsage
     static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
+        return createAppContext(mainThread, packageInfo, null);
+    }
+
+    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
+            String opPackageName) {
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
-                null);
+                null, opPackageName);
         context.setResources(packageInfo.getResources());
         return context;
     }
@@ -2461,7 +2466,7 @@
         }
 
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
-                activityToken, null, 0, classLoader);
+                activityToken, null, 0, classLoader, null);
 
         // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
         displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY;
@@ -2491,7 +2496,7 @@
     private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
             @NonNull LoadedApk packageInfo, @Nullable String splitName,
             @Nullable IBinder activityToken, @Nullable UserHandle user, int flags,
-            @Nullable ClassLoader classLoader) {
+            @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) {
         mOuterContext = this;
 
         // If creator didn't specify which storage to use, use the default
@@ -2520,9 +2525,11 @@
         mClassLoader = classLoader;
         mResourcesManager = ResourcesManager.getInstance();
 
+        String opPackageName;
+
         if (container != null) {
             mBasePackageName = container.mBasePackageName;
-            mOpPackageName = container.mOpPackageName;
+            opPackageName = container.mOpPackageName;
             setResources(container.mResources);
             mDisplay = container.mDisplay;
         } else {
@@ -2533,12 +2540,14 @@
                 // processes.  For purposes of app ops, we must then consider the context as
                 // belonging to the package of this process, not the system itself, otherwise
                 // the package+uid verifications in app ops will fail.
-                mOpPackageName = ActivityThread.currentPackageName();
+                opPackageName = ActivityThread.currentPackageName();
             } else {
-                mOpPackageName = mBasePackageName;
+                opPackageName = mBasePackageName;
             }
         }
 
+        mOpPackageName = overrideOpPackageName != null ? overrideOpPackageName : opPackageName;
+
         mContentResolver = new ApplicationContentResolver(this, mainThread);
     }
 
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index acc7094..fde1d29e 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -26,7 +26,6 @@
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.Intent;
 import android.database.Cursor;
 import android.database.CursorWrapper;
 import android.net.ConnectivityManager;
@@ -37,7 +36,6 @@
 import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.provider.Downloads;
-import android.provider.MediaStore.Images;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.text.TextUtils;
@@ -399,14 +397,14 @@
         /** if a file is designated as a MediaScanner scannable file, the following value is
          * stored in the database column {@link Downloads.Impl#COLUMN_MEDIA_SCANNED}.
          */
-        private static final int SCANNABLE_VALUE_YES = 0;
+        private static final int SCANNABLE_VALUE_YES = Downloads.Impl.MEDIA_NOT_SCANNED;
         // value of 1 is stored in the above column by DownloadProvider after it is scanned by
         // MediaScanner
         /** if a file is designated as a file that should not be scanned by MediaScanner,
          * the following value is stored in the database column
          * {@link Downloads.Impl#COLUMN_MEDIA_SCANNED}.
          */
-        private static final int SCANNABLE_VALUE_NO = 2;
+        private static final int SCANNABLE_VALUE_NO = Downloads.Impl.MEDIA_NOT_SCANNABLE;
 
         /**
          * This download is visible but only shows in the notifications
@@ -1264,19 +1262,6 @@
             throw new IllegalStateException("Failed to rename to " + after);
         }
 
-        // Update MediaProvider if necessary
-        if (mimeType.startsWith("image/")) {
-            context.getContentResolver().delete(Images.Media.EXTERNAL_CONTENT_URI,
-                    Images.Media.DATA + "=?",
-                    new String[] {
-                            before.getAbsolutePath()
-                    });
-
-            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
-            intent.setData(Uri.fromFile(after));
-            context.sendBroadcast(intent);
-        }
-
         ContentValues values = new ContentValues();
         values.put(Downloads.Impl.COLUMN_TITLE, displayName);
         values.put(Downloads.Impl._DATA, after.toString());
@@ -1329,8 +1314,7 @@
      * @param description the description that would appear for this file in Downloads App.
      * @param isMediaScannerScannable true if the file is to be scanned by MediaScanner. Files
      * scanned by MediaScanner appear in the applications used to view media (for example,
-     * Gallery app). Starting from {@link android.os.Build.VERSION_CODES#Q}, this argument is
-     * ignored and the file is always scanned by MediaScanner.
+     * Gallery app).
      * @param mimeType mimetype of the file.
      * @param path absolute pathname to the file. The file should be world-readable, so that it can
      * be managed by the Downloads App and any other app that is used to read it (for example,
@@ -1359,8 +1343,7 @@
      * @param description the description that would appear for this file in Downloads App.
      * @param isMediaScannerScannable true if the file is to be scanned by MediaScanner. Files
      * scanned by MediaScanner appear in the applications used to view media (for example,
-     * Gallery app). Starting from {@link android.os.Build.VERSION_CODES#Q}, this argument is
-     * ignored and the file is always scanned by MediaScanner.
+     * Gallery app).
      * @param mimeType mimetype of the file.
      * @param path absolute pathname to the file. The file should be world-readable, so that it can
      * be managed by the Downloads App and any other app that is used to read it (for example,
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 8953940..df04a6b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -65,6 +65,9 @@
     boolean areNotificationsEnabled(String pkg);
     int getPackageImportance(String pkg);
 
+    boolean shouldHideSilentStatusIcons(String callingPkg);
+    void setHideSilentStatusIcons(boolean hide);
+
     void setBubblesAllowed(String pkg, int uid, boolean allowed);
     boolean areBubblesAllowed(String pkg);
     boolean areBubblesAllowedForPackage(String pkg, int uid);
@@ -151,6 +154,8 @@
     void setNotificationAssistantAccessGrantedForUser(in ComponentName assistant, int userId, boolean enabled);
     List<String> getEnabledNotificationListenerPackages();
     List<ComponentName> getEnabledNotificationListeners(int userId);
+    ComponentName getAllowedNotificationAssistantForUser(int userId);
+    ComponentName getAllowedNotificationAssistant();
 
     int getZenMode();
     ZenModeConfig getZenModeConfig();
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 621f134..8207e0a 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -353,7 +354,8 @@
     public static final int IMPORTANCE_MIN = 1;
 
     /**
-     * Low notification importance: shows everywhere, but is not intrusive.
+     * Low notification importance: Shows in the shade, and potentially in the status bar
+     * (see {@link #shouldHideSilentStatusBarIcons()}), but is not audibly intrusive.
      */
     public static final int IMPORTANCE_LOW = 2;
 
@@ -826,6 +828,7 @@
     /**
      * @hide
      */
+    @TestApi
     public boolean matchesCallFilter(Bundle extras) {
         INotificationManager service = getService();
         try {
@@ -1153,6 +1156,19 @@
         }
     }
 
+    /**
+     * Checks whether the user has approved a given
+     * {@link android.service.notification.NotificationAssistantService}.
+     *
+     * <p>
+     * The assistant service must belong to the calling app.
+     *
+     * <p>
+     * Apps can request notification assistant access by sending the user to the activity that
+     * matches the system intent action
+     * TODO: STOPSHIP: Add correct intent
+     * {@link android.provider.Settings#ACTION_MANAGE_DEFAULT_APPS_SETTINGS}.
+     */
     public boolean isNotificationAssistantAccessGranted(ComponentName assistant) {
         INotificationManager service = getService();
         try {
@@ -1162,6 +1178,22 @@
         }
     }
 
+    /**
+     * Returns whether the user wants silent notifications (see {@link #IMPORTANCE_LOW} to appear
+     * in the status bar.
+     *
+     * <p>Only available for {@link #isNotificationListenerAccessGranted(ComponentName) notification
+     * listeners}.
+     */
+    public boolean shouldHideSilentStatusBarIcons() {
+        INotificationManager service = getService();
+        try {
+            return service.shouldHideSilentStatusIcons(mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide */
     public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
         INotificationManager service = getService();
@@ -1248,6 +1280,45 @@
         }
     }
 
+    /**
+     * Grants/revokes Notification Assistant access to {@code assistant} for current user.
+     *
+     * @param assistant Name of component to grant/revoke access or {@code null} to revoke access to
+     *                  current assistant
+     * @param granted Grant/revoke access
+     * @hide
+     */
+    @SystemApi
+    public void setNotificationAssistantAccessGranted(ComponentName assistant, boolean granted) {
+        INotificationManager service = getService();
+        try {
+            service.setNotificationAssistantAccessGranted(assistant, granted);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Grants/revokes Notification Assistant access to {@code assistant} for given user.
+     *
+     * @param assistant Name of component to grant/revoke access or {@code null} to revoke access to
+     *                  current assistant
+     * @param user handle to associate assistant with
+     * @param granted Grant/revoke access
+     * @hide
+     */
+    @SystemApi
+    public void setNotificationAssistantAccessGrantedForUser(ComponentName assistant,
+            UserHandle user, boolean granted) {
+        INotificationManager service = getService();
+        try {
+            service.setNotificationAssistantAccessGrantedForUser(assistant, user.getIdentifier(),
+                    granted);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide */
     public List<ComponentName> getEnabledNotificationListeners(int userId) {
         INotificationManager service = getService();
@@ -1258,6 +1329,29 @@
         }
     }
 
+    /** @hide */
+    @SystemApi
+    public @Nullable ComponentName getAllowedNotificationAssistantForUser(UserHandle user) {
+        INotificationManager service = getService();
+        try {
+            return service.getAllowedNotificationAssistantForUser(user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** @hide */
+    @SystemApi
+    public @Nullable ComponentName getAllowedNotificationAssistant() {
+        INotificationManager service = getService();
+        try {
+            return service.getAllowedNotificationAssistant();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+
     private Context mContext;
 
     private static void checkRequired(String name, Object value) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b8f4385..f0d0aad 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9614,12 +9614,18 @@
     }
 
     /**
-     * Allows the device owner to enable or disable the backup service.
+     * Allows the device owner or profile owner to enable or disable the backup service.
      *
-     * <p> Backup service manages all backup and restore mechanisms on the device. Setting this to
-     * false will prevent data from being backed up or restored.
+     * <p> Each user has its own backup service which manages the backup and restore mechanisms in
+     * that user. Disabling the backup service will prevent data from being backed up or restored.
      *
-     * <p> Backup service is off by default when device owner is present.
+     * <p> Device owner calls this API to control backup services across all users on the device.
+     * Profile owner can use this API to enable or disable the profile's backup service. However,
+     * for a managed profile its backup functionality is only enabled if both the device owner
+     * and the profile owner have enabled the backup service.
+     *
+     * <p> By default, backup service is disabled on a device with device owner, and within a
+     * managed profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param enabled {@code true} to enable the backup service, {@code false} to disable it.
@@ -9635,7 +9641,12 @@
     }
 
     /**
-     * Return whether the backup service is enabled by the device owner.
+     * Return whether the backup service is enabled by the device owner or profile owner for the
+     * current user, as previously set by {@link #setBackupServiceEnabled(ComponentName, boolean)}.
+     *
+     * <p> Whether the backup functionality is actually enabled or not depends on settings from both
+     * the current user and the device owner, please see
+     * {@link #setBackupServiceEnabled(ComponentName, boolean)} for details.
      *
      * <p> Backup service manages all backup and restore mechanisms on the device.
      *
diff --git a/core/java/android/app/prediction/AppPredictionContext.java b/core/java/android/app/prediction/AppPredictionContext.java
index 87ccb66..2fbe6e36 100644
--- a/core/java/android/app/prediction/AppPredictionContext.java
+++ b/core/java/android/app/prediction/AppPredictionContext.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -29,6 +30,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class AppPredictionContext implements Parcelable {
 
     private final int mPredictedTargetCount;
@@ -73,6 +75,17 @@
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        AppPredictionContext other = (AppPredictionContext) o;
+        return mPredictedTargetCount == other.mPredictedTargetCount
+                && mUiSurface.equals(other.mUiSurface)
+                && mPackageName.equals(other.mPackageName);
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
@@ -104,6 +117,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public static final class Builder {
 
         @NonNull
@@ -116,8 +130,12 @@
         private Bundle mExtras;
 
         /**
+         * TODO(b/123591863): Add java docs
+         *
          * @hide
          */
+        @SystemApi
+        @TestApi
         public Builder(@NonNull Context context) {
             mPackageName = context.getPackageName();
         }
diff --git a/core/java/android/app/prediction/AppPredictionManager.java b/core/java/android/app/prediction/AppPredictionManager.java
index f8578d4..99f78f1 100644
--- a/core/java/android/app/prediction/AppPredictionManager.java
+++ b/core/java/android/app/prediction/AppPredictionManager.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.Context;
 
 import com.android.internal.util.Preconditions;
@@ -26,6 +27,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class AppPredictionManager {
 
     private final Context mContext;
diff --git a/core/java/android/app/prediction/AppPredictionSessionId.java b/core/java/android/app/prediction/AppPredictionSessionId.java
index 1d7308e..1e76c24 100644
--- a/core/java/android/app/prediction/AppPredictionSessionId.java
+++ b/core/java/android/app/prediction/AppPredictionSessionId.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -26,6 +27,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class AppPredictionSessionId implements Parcelable {
 
     private final String mId;
diff --git a/core/java/android/app/prediction/AppPredictor.java b/core/java/android/app/prediction/AppPredictor.java
index 2ddbd08c..12d6ce3 100644
--- a/core/java/android/app/prediction/AppPredictor.java
+++ b/core/java/android/app/prediction/AppPredictor.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.prediction.IPredictionCallback.Stub;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
@@ -63,6 +64,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class AppPredictor {
 
     private static final String TAG = AppPredictor.class.getSimpleName();
@@ -102,6 +104,10 @@
      * Notifies the prediction service of an app target event.
      */
     public void notifyAppTargetEvent(@NonNull AppTargetEvent event) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
         try {
             mPredictionManager.notifyAppTargetEvent(mSessionId, event);
         } catch (RemoteException e) {
@@ -114,6 +120,10 @@
      */
     public void notifyLocationShown(@NonNull String launchLocation,
             @NonNull List<AppTargetId> targetIds) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
         try {
             mPredictionManager.notifyLocationShown(mSessionId, launchLocation,
                     new ParceledListSlice<>(targetIds));
@@ -130,6 +140,10 @@
      */
     public void registerPredictionUpdates(@NonNull @CallbackExecutor Executor callbackExecutor,
             @NonNull AppPredictor.Callback callback) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
         if (mRegisteredCallbacks.containsKey(callback)) {
             // Skip if this callback is already registered
             return;
@@ -149,6 +163,10 @@
      * callback until the callback is re-registered.
      */
     public void unregisterPredictionUpdates(@NonNull AppPredictor.Callback callback) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
         if (!mRegisteredCallbacks.containsKey(callback)) {
             // Skip if this callback was never registered
             return;
@@ -168,6 +186,10 @@
      * @see Callback#onTargetsAvailable(List)
      */
     public void requestPredictionUpdate() {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
         try {
             mPredictionManager.requestPredictionUpdate(mSessionId);
         } catch (RemoteException e) {
@@ -182,6 +204,10 @@
     @Nullable
     public void sortTargets(@NonNull List<AppTarget> targets,
             @NonNull Executor callbackExecutor, @NonNull Consumer<List<AppTarget>> callback) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
         try {
             mPredictionManager.sortAppTargets(mSessionId, new ParceledListSlice(targets),
                     new CallbackWrapper(callbackExecutor, callback));
@@ -206,6 +232,8 @@
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to notify app target event", e);
             }
+        } else {
+            throw new IllegalStateException("This client has already been destroyed.");
         }
     }
 
@@ -222,6 +250,16 @@
     }
 
     /**
+     * TODO(b/123591863): Add java docs
+     *
+     * @hide
+     */
+    @TestApi
+    public AppPredictionSessionId getSessionId() {
+        return mSessionId;
+    }
+
+    /**
      * Callback for receiving prediction updates.
      */
     public interface Callback {
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index 99c1c44..b924cec 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.pm.ShortcutInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -30,6 +31,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class AppTarget implements Parcelable {
 
     private final AppTargetId mId;
@@ -42,8 +44,12 @@
     private int mRank;
 
     /**
+     * TODO(b/123591863): Add java docs
+     *
      * @hide
      */
+    @SystemApi
+    @TestApi
     public AppTarget(@NonNull AppTargetId id, @NonNull String packageName,
             @Nullable String className, @NonNull UserHandle user) {
         mId = id;
@@ -55,15 +61,19 @@
     }
 
     /**
+     * TODO(b/123591863): Add java docs
+     *
      * @hide
      */
-    public AppTarget(@NonNull AppTargetId id, @NonNull ShortcutInfo shortcutInfo) {
+    @SystemApi
+    public AppTarget(@NonNull AppTargetId id, @NonNull ShortcutInfo shortcutInfo,
+            @Nullable String className) {
         mId = id;
         mShortcutInfo = Preconditions.checkNotNull(shortcutInfo);
 
         mPackageName = mShortcutInfo.getPackage();
         mUser = mShortcutInfo.getUserHandle();
-        mClassName = null;
+        mClassName = className;
     }
 
     private AppTarget(Parcel parcel) {
@@ -71,13 +81,12 @@
         mShortcutInfo = parcel.readTypedObject(ShortcutInfo.CREATOR);
         if (mShortcutInfo == null) {
             mPackageName = parcel.readString();
-            mClassName = parcel.readString();
             mUser = UserHandle.of(parcel.readInt());
         } else {
             mPackageName = mShortcutInfo.getPackage();
             mUser = mShortcutInfo.getUserHandle();
-            mClassName = null;
         }
+        mClassName = parcel.readString();
         mRank = parcel.readInt();
     }
 
@@ -129,11 +138,32 @@
         mRank = rank;
     }
 
+    /**
+     * Returns the rank for the target.
+     */
     public int getRank() {
         return mRank;
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        AppTarget other = (AppTarget) o;
+        boolean sameClassName = (mClassName == null && other.mClassName == null)
+                || (mClassName != null && mClassName.equals(other.mClassName));
+        boolean sameShortcutInfo = (mShortcutInfo == null && other.mShortcutInfo == null)
+                || (mShortcutInfo != null && other.mShortcutInfo != null
+                        && mShortcutInfo.getId() == other.mShortcutInfo.getId());
+        return mId.equals(other.mId)
+                && mPackageName.equals(other.mPackageName)
+                && sameClassName
+                && mUser.equals(other.mUser)
+                && sameShortcutInfo
+                && mRank == other.mRank;
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
@@ -144,9 +174,9 @@
         dest.writeTypedObject(mShortcutInfo, flags);
         if (mShortcutInfo == null) {
             dest.writeString(mPackageName);
-            dest.writeString(mClassName);
             dest.writeInt(mUser.getIdentifier());
         }
+        dest.writeString(mClassName);
         dest.writeInt(mRank);
     }
 
diff --git a/core/java/android/app/prediction/AppTargetEvent.java b/core/java/android/app/prediction/AppTargetEvent.java
index 18317e1..37e41de 100644
--- a/core/java/android/app/prediction/AppTargetEvent.java
+++ b/core/java/android/app/prediction/AppTargetEvent.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -30,6 +31,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class AppTargetEvent implements Parcelable {
 
     /**
@@ -96,6 +98,16 @@
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        AppTargetEvent other = (AppTargetEvent) o;
+        return mTarget.equals(other.mTarget)
+                && mLocation.equals(other.mLocation)
+                && mAction == other.mAction;
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
@@ -126,6 +138,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public static final class Builder {
         private AppTarget mTarget;
         private String mLocation;
diff --git a/core/java/android/app/prediction/AppTargetId.java b/core/java/android/app/prediction/AppTargetId.java
index 0b8fb47..639ba78 100644
--- a/core/java/android/app/prediction/AppTargetId.java
+++ b/core/java/android/app/prediction/AppTargetId.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -25,14 +26,19 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class AppTargetId implements Parcelable {
 
     @NonNull
     private final String mId;
 
     /**
+     * TODO(b/123591863): Add java docs
+     *
      * @hide
      */
+    @SystemApi
+    @TestApi
     public AppTargetId(@NonNull String id) {
         mId = id;
     }
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index d1bc377..50bb3c7 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -24,6 +24,8 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IOnAppsChangedListener;
 import android.content.pm.LauncherApps;
+import android.content.pm.IPackageInstallerCallback;
+import android.content.pm.PackageInstaller;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
@@ -44,6 +46,9 @@
             String callingPackage, String packageName, in UserHandle user);
     ActivityInfo resolveActivity(
             String callingPackage, in ComponentName component, in UserHandle user);
+    void startSessionDetailsActivityAsUser(in IApplicationThread caller, String callingPackage,
+                in PackageInstaller.SessionInfo sessionInfo, in Rect sourceBounds, in Bundle opts,
+                in UserHandle user);
     void startActivityAsUser(in IApplicationThread caller, String callingPackage,
             in ComponentName component, in Rect sourceBounds,
             in Bundle opts, in UserHandle user);
@@ -79,4 +84,9 @@
             String callingPackage, String packageName, in UserHandle user);
     IntentSender getShortcutConfigActivityIntent(String callingPackage, in ComponentName component,
             in UserHandle user);
+
+    // Unregister is performed using package installer
+    void registerPackageInstallerCallback(String callingPackage,
+            in IPackageInstallerCallback callback);
+    ParceledListSlice getAllSessions(String callingPackage);
 }
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 98dd9b3..b0d16cd 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -32,6 +33,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.pm.PackageInstaller.SessionCallback;
+import android.content.pm.PackageInstaller.SessionCallbackDelegate;
+import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageManager.ApplicationInfoFlags;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
@@ -65,7 +69,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Class for retrieving a list of launchable activities for the current user and any associated
@@ -154,8 +160,8 @@
     private final PackageManager mPm;
     private final UserManager mUserManager;
 
-    private List<CallbackMessageHandler> mCallbacks
-            = new ArrayList<CallbackMessageHandler>();
+    private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>();
+    private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>();
 
     /**
      * Callbacks for package changes to this and related managed profiles.
@@ -572,6 +578,24 @@
     }
 
     /**
+     * Starts an activity to show the details of the specified session.
+     *
+     * @param sessionInfo The SessionInfo of the session
+     * @param sourceBounds The Rect containing the source bounds of the clicked icon
+     * @param opts Options to pass to startActivity
+     */
+    public void startPackageInstallerSessionDetailsActivity(SessionInfo sessionInfo,
+            Rect sourceBounds, Bundle opts) {
+        try {
+            mService.startSessionDetailsActivityAsUser(mContext.getIApplicationThread(),
+                    mContext.getPackageName(), sessionInfo, sourceBounds, opts,
+                    sessionInfo.getUser());
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Starts the settings activity to show the application details for a
      * package in the specified profile.
      *
@@ -1131,7 +1155,7 @@
     }
 
     /**
-     * Registers a callback for changes to packages in current and managed profiles.
+     * Registers a callback for changes to packages in this user and managed profiles.
      *
      * @param callback The callback to register.
      */
@@ -1140,7 +1164,7 @@
     }
 
     /**
-     * Registers a callback for changes to packages in current and managed profiles.
+     * Registers a callback for changes to packages in this user and managed profiles.
      *
      * @param callback The callback to register.
      * @param handler that should be used to post callbacks on, may be null.
@@ -1446,6 +1470,64 @@
     }
 
     /**
+     * Register a callback to watch for session lifecycle events in this user and managed profiles.
+     * @param callback The callback to register.
+     * @param executor {@link Executor} to handle the callbacks, cannot be null.
+     *
+     * @see PackageInstaller#registerSessionCallback(SessionCallback)
+     */
+    public void registerPackageInstallerSessionCallback(
+            @NonNull @CallbackExecutor Executor executor, @NonNull SessionCallback callback) {
+        if (executor == null) {
+            throw new NullPointerException("Executor must not be null");
+        }
+
+        synchronized (mDelegates) {
+            final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
+                    executor);
+            try {
+                mService.registerPackageInstallerCallback(mContext.getPackageName(),
+                        delegate);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+            mDelegates.add(delegate);
+        }
+    }
+
+    /**
+     * Unregisters a callback that was previously registered.
+     *
+     * @param callback The callback to unregister.
+     * @see #registerPackageInstallerSessionCallback(Executor, SessionCallback)
+     */
+    public void unregisterPackageInstallerSessionCallback(SessionCallback callback) {
+        synchronized (mDelegates) {
+            for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
+                final SessionCallbackDelegate delegate = i.next();
+                if (delegate.mCallback == callback) {
+                    mPm.getPackageInstaller().unregisterSessionCallback(delegate.mCallback);
+                    i.remove();
+                }
+            }
+        }
+    }
+
+    /**
+     * Return list of all known install sessions in this user and managed profiles, regardless
+     * of the installer.
+     *
+     * @see PackageInstaller#getAllSessions()
+     */
+    public @NonNull List<SessionInfo> getAllPackageInstallerSessions() {
+        try {
+            return mService.getAllSessions(mContext.getPackageName()).getList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * A helper method to extract a {@link PinItemRequest} set to
      * the {@link #EXTRA_PIN_ITEM_REQUEST} extra.
      */
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 2dc014c..4f674bd 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -36,20 +36,21 @@
 import android.os.Build;
 import android.os.FileBridge;
 import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
+import android.os.HandlerExecutor;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.os.ParcelableException;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.util.ExceptionUtils;
 
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -61,6 +62,7 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Offers the ability to install, upgrade, and remove applications on the
@@ -659,8 +661,7 @@
     }
 
     /** {@hide} */
-    private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements
-            Handler.Callback {
+    static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub {
         private static final int MSG_SESSION_CREATED = 1;
         private static final int MSG_SESSION_BADGING_CHANGED = 2;
         private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
@@ -668,63 +669,41 @@
         private static final int MSG_SESSION_FINISHED = 5;
 
         final SessionCallback mCallback;
-        final Handler mHandler;
+        final Executor mExecutor;
 
-        public SessionCallbackDelegate(SessionCallback callback, Looper looper) {
+        SessionCallbackDelegate(SessionCallback callback, Executor executor) {
             mCallback = callback;
-            mHandler = new Handler(looper, this);
-        }
-
-        @Override
-        public boolean handleMessage(Message msg) {
-            final int sessionId = msg.arg1;
-            switch (msg.what) {
-                case MSG_SESSION_CREATED:
-                    mCallback.onCreated(sessionId);
-                    return true;
-                case MSG_SESSION_BADGING_CHANGED:
-                    mCallback.onBadgingChanged(sessionId);
-                    return true;
-                case MSG_SESSION_ACTIVE_CHANGED:
-                    final boolean active = msg.arg2 != 0;
-                    mCallback.onActiveChanged(sessionId, active);
-                    return true;
-                case MSG_SESSION_PROGRESS_CHANGED:
-                    mCallback.onProgressChanged(sessionId, (float) msg.obj);
-                    return true;
-                case MSG_SESSION_FINISHED:
-                    mCallback.onFinished(sessionId, msg.arg2 != 0);
-                    return true;
-            }
-            return false;
+            mExecutor = executor;
         }
 
         @Override
         public void onSessionCreated(int sessionId) {
-            mHandler.obtainMessage(MSG_SESSION_CREATED, sessionId, 0).sendToTarget();
+            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback,
+                    sessionId).recycleOnUse());
         }
 
         @Override
         public void onSessionBadgingChanged(int sessionId) {
-            mHandler.obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, 0).sendToTarget();
+            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged,
+                    mCallback, sessionId).recycleOnUse());
         }
 
         @Override
         public void onSessionActiveChanged(int sessionId, boolean active) {
-            mHandler.obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, active ? 1 : 0)
-                    .sendToTarget();
+            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged,
+                    mCallback, sessionId, active).recycleOnUse());
         }
 
         @Override
         public void onSessionProgressChanged(int sessionId, float progress) {
-            mHandler.obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, 0, progress)
-                    .sendToTarget();
+            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged,
+                    mCallback, sessionId, progress).recycleOnUse());
         }
 
         @Override
         public void onSessionFinished(int sessionId, boolean success) {
-            mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0)
-                    .sendToTarget();
+            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished,
+                    mCallback, sessionId, success).recycleOnUse());
         }
     }
 
@@ -758,7 +737,7 @@
     public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
         synchronized (mDelegates) {
             final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
-                    handler.getLooper());
+                    new HandlerExecutor(handler));
             try {
                 mInstaller.registerCallback(delegate, mUserId);
             } catch (RemoteException e) {
@@ -1649,6 +1628,8 @@
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public int sessionId;
         /** {@hide} */
+        public int userId;
+        /** {@hide} */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public String installerPackageName;
         /** {@hide} */
@@ -1720,6 +1701,7 @@
         /** {@hide} */
         public SessionInfo(Parcel source) {
             sessionId = source.readInt();
+            userId = source.readInt();
             installerPackageName = source.readString();
             resolvedBaseCodePath = source.readString();
             progress = source.readFloat();
@@ -1761,6 +1743,13 @@
         }
 
         /**
+         * Return the user associated with this session.
+         */
+        public UserHandle getUser() {
+            return new UserHandle(userId);
+        }
+
+        /**
          * Return the package name of the app that owns this session.
          */
         public @Nullable String getInstallerPackageName() {
@@ -2091,6 +2080,7 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(sessionId);
+            dest.writeInt(userId);
             dest.writeString(installerPackageName);
             dest.writeString(resolvedBaseCodePath);
             dest.writeFloat(progress);
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index f9c2c3e..a1b0803 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -2644,10 +2644,29 @@
              * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
              * before it is closed and removed from the pool.
              *
+             * <p>DO NOT USE this method unless you fully understand the implication
+             * of what it does.
+             * A connection timeout allows the system to internally close a connection to a SQLite
+             * database after a given timeout.
+             * This is good for reducing app's memory consumption, but it has
+             * side effects that are hard to predict. For example, SQLite internally maintains
+             * a lot of "per-connection" states that apps can typically modify with a {@code PRAGMA}
+             * statement, and such states will be reset once the connection is closed.
+             * The system does not provide a callback that would allow apps to
+             * reconfigure a newly created connection and thus there's no way to re-configure
+             * connections when they're re-made internally. Do not use it unless you're sure
+             * your app uses no per-connection states.
+             *
              * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
              * to allow unlimited idle connections.
+             *
+             * @see SQLiteOpenHelper#setIdleConnectionTimeout(long)
+             *
+             * @deprecated DO NOT USE this method unless you fully understand the implication
+             * of what it does.
              */
             @NonNull
+            @Deprecated
             public Builder setIdleConnectionTimeout(
                     @IntRange(from = 0) long idleConnectionTimeoutMs) {
                 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 19c6745..ceeecbc 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -263,9 +263,21 @@
      * <p>This method should be called from the constructor of the subclass,
      * before opening the database
      *
+     * <p>DO NOT USE this method unless you fully understand the implication
+     * of what it does.
+     * See the javadoc of
+     * {@link SQLiteDatabase.OpenParams.Builder#setIdleConnectionTimeout(long)}
+     * for the details.
+     *
      * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE} value
      * to allow unlimited idle connections.
+     *
+     * @see SQLiteDatabase.OpenParams.Builder#setIdleConnectionTimeout(long)
+     *
+     * @deprecated DO NOT USE this method unless you fully understand the implication
+     * of what it does.
      */
+    @Deprecated
     public void setIdleConnectionTimeout(@IntRange(from = 0) final long idleConnectionTimeoutMs) {
         synchronized (this) {
             if (mDatabase != null && mDatabase.isOpen()) {
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index 3b01266..3ab35e1 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -117,4 +117,17 @@
         } catch (RemoteException e) {
         }
     }
+
+    /**
+     * Log a captive portal login event.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public void logEvent(int eventId, String packageName) {
+        try {
+            ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
+        } catch (RemoteException e) {
+        }
+    }
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ef8ca9e..869cf64 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1033,34 +1033,6 @@
         }
     }
 
-    /**
-     * Configures an always-on VPN connection through a specific application.
-     * This connection is automatically granted and persisted after a reboot.
-     *
-     * <p>The designated package should declare a {@link VpnService} in its
-     *    manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
-     *    otherwise the call will fail.
-     *
-     * @param userId The identifier of the user to set an always-on VPN for.
-     * @param vpnPackage The package name for an installed VPN app on the device, or {@code null}
-     *                   to remove an existing always-on VPN configuration.
-     * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
-     *        {@code false} otherwise.
-     * @return {@code true} if the package is set as always-on VPN controller;
-     *         {@code false} otherwise.
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
-    public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
-            boolean lockdownEnabled) {
-        try {
-            return mService.setAlwaysOnVpnPackage(
-                    userId, vpnPackage, lockdownEnabled, /* whitelist */ null);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
    /**
      * Returns the package name of the currently set always-on VPN application.
      * If there is no always-on VPN set, or the VPN is provided by the system instead
diff --git a/core/java/android/net/ICaptivePortal.aidl b/core/java/android/net/ICaptivePortal.aidl
index 56ae57d..707b4f6 100644
--- a/core/java/android/net/ICaptivePortal.aidl
+++ b/core/java/android/net/ICaptivePortal.aidl
@@ -22,4 +22,5 @@
  */
 oneway interface ICaptivePortal {
     void appResponse(int response);
+    void logEvent(int eventId, String packageName);
 }
diff --git a/core/java/android/net/INetworkMonitorCallbacks.aidl b/core/java/android/net/INetworkMonitorCallbacks.aidl
index 0bc2575..a8682f9 100644
--- a/core/java/android/net/INetworkMonitorCallbacks.aidl
+++ b/core/java/android/net/INetworkMonitorCallbacks.aidl
@@ -26,4 +26,5 @@
     void notifyPrivateDnsConfigResolved(in PrivateDnsConfigParcel config);
     void showProvisioningNotification(String action);
     void hideProvisioningNotification();
+    void logCaptivePortalLoginEvent(int eventId, String packageName);
 }
\ No newline at end of file
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index dc099a4..784f233 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -791,6 +791,27 @@
         }
 
         /**
+         * Marks the VPN network as metered. A VPN network is classified as metered when the user is
+         * sensitive to heavy data usage due to monetary costs and/or data limitations. In such
+         * cases, you should set this to {@code true} so that apps on the system can avoid doing
+         * large data transfers. Otherwise, set this to {@code false}. Doing so would cause VPN
+         * network to inherit its meteredness from its underlying networks.
+         *
+         * <p>VPN apps targeting {@link android.os.Build.VERSION_CODES#Q} or above will be
+         * considered metered by default.
+         *
+         * @param isMetered {@code true} if VPN network should be treated as metered regardless of
+         *     underlying network meteredness
+         * @return this {@link Builder} object to facilitate chaining method calls
+         * @see #setUnderlyingNetworks(Networks[])
+         * @see ConnectivityManager#isActiveNetworkMetered()
+         */
+        public Builder setMetered(boolean isMetered) {
+            mConfig.isMetered = isMetered;
+            return this;
+        }
+
+        /**
          * Create a VPN interface using the parameters supplied to this
          * builder. The interface works on IP packets, and a file descriptor
          * is returned for the application to access them. Each read
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
new file mode 100644
index 0000000..b568f15
--- /dev/null
+++ b/core/java/android/os/OWNERS
@@ -0,0 +1,2 @@
+# Zygote
+per-file ZygoteProcess.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 8a52f1f..3e5bd4b 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -138,8 +138,8 @@
      * Action used to help apps show calendar events in the managed profile.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_VIEW_WORK_CALENDAR_EVENT =
-            "android.provider.calendar.action.VIEW_WORK_CALENDAR_EVENT";
+    public static final String ACTION_VIEW_MANAGED_PROFILE_CALENDAR_EVENT =
+            "android.provider.calendar.action.VIEW_MANAGED_PROFILE_CALENDAR_EVENT";
 
     /**
      * Intent Extras key: {@link EventsColumns#CUSTOM_APP_URI} for the event in
@@ -166,7 +166,7 @@
     public static final String EXTRA_EVENT_ALL_DAY = "allDay";
 
     /**
-     * Intent Extras key: The id of an event.
+     * Intent Extras key: An extra of type {@code long} holding the id of an event.
      */
     public static final String EXTRA_EVENT_ID = "id";
 
@@ -218,7 +218,7 @@
      * When this API is called, the system will attempt to start an activity
      * in the managed profile with an intent targeting the same caller package.
      * The intent will have its action set to
-     * {@link CalendarContract#ACTION_VIEW_WORK_CALENDAR_EVENT} and contain extras
+     * {@link CalendarContract#ACTION_VIEW_MANAGED_PROFILE_CALENDAR_EVENT} and contain extras
      * corresponding to the API's arguments. A calendar app intending to support
      * cross-profile events viewing should handle this intent, parse the arguments
      * and show the appropriate UI.
@@ -226,10 +226,10 @@
      * @param context the context.
      * @param eventId the id of the event to be viewed. Will be put into {@link #EXTRA_EVENT_ID}
      *                field of the intent.
-     * @param start the start time of the event. Will be put into {@link #EXTRA_EVENT_BEGIN_TIME}
-     *              field of the intent.
-     * @param end the end time of the event. Will be put into {@link #EXTRA_EVENT_END_TIME} field
-     *            of the intent.
+     * @param startMs the start time of the event in milliseconds since epoch.
+     *                Will be put into {@link #EXTRA_EVENT_BEGIN_TIME} field of the intent.
+     * @param endMs the end time of the event in milliseconds since epoch.
+     *              Will be put into {@link #EXTRA_EVENT_END_TIME} field of the intent.
      * @param allDay if the event is an all-day event. Will be put into
      *               {@link #EXTRA_EVENT_ALL_DAY} field of the intent.
      * @param flags flags to be set on the intent via {@link Intent#setFlags}
@@ -241,12 +241,12 @@
      * @see #EXTRA_EVENT_ALL_DAY
      */
     public static boolean startViewCalendarEventInManagedProfile(@NonNull Context context,
-            long eventId, long start, long end, boolean allDay, int flags) {
+            long eventId, long startMs, long endMs, boolean allDay, int flags) {
         Preconditions.checkNotNull(context, "Context is null");
         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
-        return dpm.startViewCalendarEventInManagedProfile(eventId, start,
-                end, allDay, flags);
+        return dpm.startViewCalendarEventInManagedProfile(eventId, startMs,
+                endMs, allDay, flags);
     }
 
     /**
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 0b23fe3e..92650e1 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -160,6 +160,18 @@
     }
 
     /**
+     * Namespace for all activity manager related features that are used at the native level.
+     * These features are applied at reboot.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface ActivityManagerNativeBoot {
+        String NAMESPACE = "activity_manager_native_boot";
+        String OFFLOAD_QUEUE_ENABLED = "offload_queue_enabled";
+    }
+
+    /**
      * Namespace for attention-based features provided by on-device machine intelligence.
      *
      * @hide
@@ -169,10 +181,10 @@
         String NAMESPACE = "intelligence_attention";
 
         /** If {@code true}, enables the attention features. */
-        String PROPERTY_ATTENTION_ENABLED = "attention_enabled";
+        String ATTENTION_ENABLED = "attention_enabled";
 
         /** Settings for the attention features. */
-        String PROPERTY_ATTENTION_SETTINGS = "attention_settings";
+        String ATTENTION_SETTINGS = "attention_settings";
     }
 
     /**
@@ -191,12 +203,12 @@
          * @hide
          */
         @SystemApi
-        String PROPERTY_PERMISSIONS_HUB_ENABLED = "enable_permissions_hub";
+        String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
 
         /**
          * Whether to show location access check notifications.
          */
-        String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED = "enable_location_access_check";
+        String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED = "location_access_check_enabled";
     }
 
     /**
@@ -208,26 +220,29 @@
     public interface Telephony {
         String NAMESPACE = "telephony";
         /**
-         * Whether to apply ramping ringer on incoming phone calls.
-         */
-        String PROPERTY_ENABLE_RAMPING_RINGER = "enable_ramping_ringer";
-        /**
          * Ringer ramping time in milliseconds.
          */
-        String PROPERTY_RAMPING_RINGER_DURATION = "ramping_duration";
+        String RAMPING_RINGER_DURATION = "ramping_ringer_duration";
+        /**
+         * Whether to apply ramping ringer on incoming phone calls.
+         */
+        String RAMPING_RINGER_ENABLED = "ramping_ringer_enabled";
+        /**
+         * Vibration time in milliseconds before ramping ringer starts.
+         */
+        String RAMPING_RINGER_VIBRATION_DURATION = "ramping_ringer_vibration_duration";
     }
 
     /**
-     * Namespace for Full Stack Integrity to run privileged apps only in JIT mode. The flag applies
-     * at process start, so reboot is a way to bring the device to a clean state.
+     * Namespace for how dex runs.  The feature may requires reboot to a clean state.
      *
      * @hide
      */
     @SystemApi
-    public interface FsiBoot {
-        String NAMESPACE = "fsi_boot";
-        String OOB_ENABLED = "oob_enabled";
-        String OOB_WHITELIST = "oob_whitelist";
+    public interface DexBoot {
+        String NAMESPACE = "dex_boot";
+        String PRIV_APPS_OOB_ENABLED = "priv_apps_oob_enabled";
+        String PRIV_APPS_OOB_WHITELIST = "priv_apps_oob_whitelist";
     }
 
     /**
@@ -250,6 +265,7 @@
         String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2";
         String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3";
         String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4";
+        String KEY_COMPACT_STATSD_SAMPLE_RATE = "compact_statsd_sample_rate";
 
         /**
          * Maximum number of cached processes. See
@@ -268,10 +284,10 @@
         String NAMESPACE = "attention_manager_service";
 
         /** If {@code true}, enables {@link AttentionManagerService} features. */
-        String PROPERTY_SERVICE_ENABLED = "service_enabled";
+        String SERVICE_ENABLED = "service_enabled";
 
         /** Allows a CTS to inject a fake implementation. */
-        String PROPERTY_COMPONENT_NAME = "component_name";
+        String COMPONENT_NAME = "component_name";
     }
 
     /**
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 63bbb9c..89d1c44 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -419,12 +419,20 @@
 
         /**
          * The column that is used to remember whether the media scanner was invoked.
-         * It can take the values: null or 0(not scanned), 1(scanned), 2 (not scannable).
+         * It can take the values: {@link #MEDIA_NOT_SCANNED}, {@link #MEDIA_SCANNED} or
+         * {@link #MEDIA_NOT_SCANNABLE} or {@code null}. If it's value is {@code null}, it will be
+         * treated as {@link #MEDIA_NOT_SCANNED}.
+         *
          * <P>Type: TEXT</P>
          */
         @UnsupportedAppUsage
         public static final String COLUMN_MEDIA_SCANNED = "scanned";
 
+        /** Possible values for column {@link #COLUMN_MEDIA_SCANNED} */
+        public static final int MEDIA_NOT_SCANNED = 0;
+        public static final int MEDIA_SCANNED = 1;
+        public static final int MEDIA_NOT_SCANNABLE = 2;
+
         /**
          * The column with errorMsg for a failed downloaded.
          * Used only for debugging purposes.
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 124c50a..0743c23 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -641,6 +641,8 @@
          * location. For example, when this value is left undefined, pending
          * {@link MediaStore.Audio.Media} items are stored under
          * {@link Environment#DIRECTORY_MUSIC}.
+         *
+         * @see MediaColumns#PRIMARY_DIRECTORY
          */
         public void setPrimaryDirectory(@Nullable String primaryDirectory) {
             this.primaryDirectory = primaryDirectory;
@@ -652,6 +654,8 @@
          * <p>
          * You may leave this value undefined to store the media as a direct
          * descendant of the {@link #setPrimaryDirectory(String)} location.
+         *
+         * @see MediaColumns#SECONDARY_DIRECTORY
          */
         public void setSecondaryDirectory(@Nullable String secondaryDirectory) {
             this.secondaryDirectory = secondaryDirectory;
@@ -980,6 +984,26 @@
          * Type: TEXT
          */
         public static final String OWNER_PACKAGE_NAME = "owner_package_name";
+
+        /**
+         * The primary directory name this media exists under. The value may be
+         * {@code NULL} if the media doesn't have a primary directory name.
+         * <p>
+         * Type: TEXT
+         *
+         * @see PendingParams#setPrimaryDirectory(String)
+         */
+        public static final String PRIMARY_DIRECTORY = "primary_directory";
+
+        /**
+         * The secondary directory name this media exists under. The value may
+         * be {@code NULL} if the media doesn't have a secondary directory name.
+         * <p>
+         * Type: TEXT
+         *
+         * @see PendingParams#setSecondaryDirectory(String)
+         */
+        public static final String SECONDARY_DIRECTORY = "secondary_directory";
     }
 
     /**
@@ -1428,13 +1452,20 @@
             public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
 
             /**
-             * The secondary bucket ID of this media item. This can be useful to
-             * present the user a second-level clustering of related media
-             * items. This is a read-only column that is automatically computed.
+             * The group ID of this media item. This can be useful to present
+             * the user a grouping of related media items, such a burst of
+             * images, or a {@code JPG} and {@code DNG} version of the same
+             * image.
+             * <p>
+             * This is a read-only column that is automatically computed based
+             * on the first portion of the filename. For example,
+             * {@code IMG1024.BURST001.JPG} and {@code IMG1024.BURST002.JPG}
+             * will have the same {@link #GROUP_ID} because the first portion of
+             * their filenames is identical.
              * <p>
              * Type: INTEGER
              */
-            public static final String SECONDARY_BUCKET_ID = "secondary_bucket_id";
+            public static final String GROUP_ID = "group_id";
         }
 
         public static final class Media implements ImageColumns {
@@ -2697,13 +2728,20 @@
             public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
 
             /**
-             * The secondary bucket ID of this media item. This can be useful to
-             * present the user a second-level clustering of related media
-             * items. This is a read-only column that is automatically computed.
+             * The group ID of this media item. This can be useful to present
+             * the user a grouping of related media items, such a burst of
+             * images, or a {@code JPG} and {@code DNG} version of the same
+             * image.
+             * <p>
+             * This is a read-only column that is automatically computed based
+             * on the first portion of the filename. For example,
+             * {@code IMG1024.BURST001.JPG} and {@code IMG1024.BURST002.JPG}
+             * will have the same {@link #GROUP_ID} because the first portion of
+             * their filenames is identical.
              * <p>
              * Type: INTEGER
              */
-            public static final String SECONDARY_BUCKET_ID = "secondary_bucket_id";
+            public static final String GROUP_ID = "group_id";
 
             /**
              * The bookmark for the video. Time in ms. Represents the location in the video that the
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5151e29..afa2110 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5874,30 +5874,24 @@
                 "unknown_sources_default_reversed";
 
         /**
-         * Comma-separated list of location providers that activities may access. Do not rely on
-         * this value being present in settings.db or on ContentObserver notifications on the
+         * Comma-separated list of location providers that are accessible. Do not rely on
+         * this value being present or correct, or on ContentObserver notifications on the
          * corresponding Uri.
          *
-         * @deprecated Providers should not be controlled individually. See {@link #LOCATION_MODE}
-          * documentation for information on reading/writing location information.
+         * @deprecated The preferred methods for checking provider status and listening for changes
+         * are via {@link LocationManager#isProviderEnabled(String)} and
+         * {@link LocationManager#PROVIDERS_CHANGED_ACTION}.
          */
         @Deprecated
         public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
 
         /**
-         * The degree of location access enabled by the user.
-         * <p>
-         * When used with {@link #putInt(ContentResolver, String, int)}, must be one of {@link
-         * #LOCATION_MODE_HIGH_ACCURACY}, {@link #LOCATION_MODE_SENSORS_ONLY}, {@link
-         * #LOCATION_MODE_BATTERY_SAVING}, or {@link #LOCATION_MODE_OFF}. When used with {@link
-         * #getInt(ContentResolver, String)}, the caller must gracefully handle additional location
-         * modes that might be added in the future.
-         * <p>
-         * Note: do not rely on this value being present in settings.db or on ContentObserver
-         * notifications for the corresponding Uri. Use {@link LocationManager#MODE_CHANGED_ACTION}
-         * to receive changes in this value.
+         * The current location mode of the device. Do not rely on this value being present or on
+         * ContentObserver notifications on the corresponding Uri.
          *
-         * @deprecated To check location mode, use {@link LocationManager#isLocationEnabled()}.
+         * @deprecated The preferred methods for checking location mode and listening for changes
+         * are via {@link LocationManager#isLocationEnabled()} and
+         * {@link LocationManager#MODE_CHANGED_ACTION}.
          */
         @Deprecated
         public static final String LOCATION_MODE = "location_mode";
@@ -5924,7 +5918,7 @@
         public static final int LOCATION_CHANGER_QUICK_SETTINGS = 2;
 
         /**
-         * Location access disabled.
+         * Location mode is off.
          *
          * @deprecated See {@link #LOCATION_MODE}.
          */
@@ -5932,32 +5926,39 @@
         public static final int LOCATION_MODE_OFF = 0;
 
         /**
-         * Network Location Provider disabled, but GPS and other sensors enabled.
+         * This mode no longer has any distinct meaning, but is interpreted as the location mode is
+         * on.
          *
-         * @deprecated To check location status, use {@link LocationManager#isLocationEnabled()}. To
-         *             get the status of a location provider, use
-         *             {@link LocationManager#isProviderEnabled(String)}.
+         * @deprecated See {@link #LOCATION_MODE_ON}.
          */
         @Deprecated
         public static final int LOCATION_MODE_SENSORS_ONLY = 1;
 
         /**
-         * Reduced power usage, such as limiting the number of GPS updates per hour. Requests
-         * with {@link android.location.Criteria#POWER_HIGH} may be downgraded to
-         * {@link android.location.Criteria#POWER_MEDIUM}.
+         * This mode no longer has any distinct meaning, but is interpreted as the location mode is
+         * on.
          *
-         * @deprecated See {@link #LOCATION_MODE}.
+         * @deprecated See {@link #LOCATION_MODE_ON}.
          */
         @Deprecated
         public static final int LOCATION_MODE_BATTERY_SAVING = 2;
 
         /**
-         * Best-effort location computation allowed.
+         * This mode no longer has any distinct meaning, but is interpreted as the location mode is
+         * on.
+         *
+         * @deprecated See {@link #LOCATION_MODE_ON}.
+         */
+        @Deprecated
+        public static final int LOCATION_MODE_HIGH_ACCURACY = 3;
+
+        /**
+         * Location mode is on.
          *
          * @deprecated See {@link #LOCATION_MODE}.
          */
         @Deprecated
-        public static final int LOCATION_MODE_HIGH_ACCURACY = 3;
+        public static final int LOCATION_MODE_ON = LOCATION_MODE_HIGH_ACCURACY;
 
         /**
          * A flag containing settings used for biometric weak
@@ -10600,6 +10601,18 @@
         private static final Validator WIFI_PNO_RECENCY_SORTING_ENABLED_VALIDATOR =
                 BOOLEAN_VALIDATOR;
 
+        /**
+         * Setting to enable the Wi-Fi link probing.
+         * Disabled by default, and setting it to 1 will enable it.
+         * The value is boolean (0 or 1).
+         * @hide
+         */
+        public static final String WIFI_LINK_PROBING_ENABLED =
+                "wifi_link_probing_enabled";
+
+        private static final Validator WIFI_LINK_PROBING_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
        /**
         * The maximum number of times we will retry a connection to an access
         * point for which we have failed in acquiring an IP address from DHCP.
@@ -13393,6 +13406,7 @@
                     WIFI_PNO_FREQUENCY_CULLING_ENABLED_VALIDATOR);
             VALIDATORS.put(WIFI_PNO_RECENCY_SORTING_ENABLED,
                     WIFI_PNO_RECENCY_SORTING_ENABLED_VALIDATOR);
+            VALIDATORS.put(WIFI_LINK_PROBING_ENABLED, WIFI_LINK_PROBING_ENABLED_VALIDATOR);
         }
 
         /**
diff --git a/core/java/android/service/appprediction/AppPredictionService.java b/core/java/android/service/appprediction/AppPredictionService.java
index b77405a..d012851 100644
--- a/core/java/android/service/appprediction/AppPredictionService.java
+++ b/core/java/android/service/appprediction/AppPredictionService.java
@@ -21,6 +21,7 @@
 import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.Service;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppPredictionSessionId;
@@ -49,6 +50,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public abstract class AppPredictionService extends Service {
 
     private static final String TAG = "AppPredictionService";
@@ -140,6 +142,7 @@
 
     @Override
     public final IBinder onBind(Intent intent) {
+        // TODO(b/111701043): Verify that the action is valid
         return mInterface.asBinder();
     }
 
@@ -228,6 +231,7 @@
     public void onStopPredictionUpdates() {}
 
     private void doRequestPredictionUpdate(@NonNull AppPredictionSessionId sessionId) {
+        // Just an optimization, if there are no callbacks, then don't bother notifying the service
         final ArrayList<CallbackWrapper> callbacks = mSessionCallbacks.get(sessionId);
         if (callbacks != null && !callbacks.isEmpty()) {
             onRequestPredictionUpdate(sessionId);
diff --git a/core/java/android/service/attention/AttentionService.java b/core/java/android/service/attention/AttentionService.java
index f6e448dc..24d74ff 100644
--- a/core/java/android/service/attention/AttentionService.java
+++ b/core/java/android/service/attention/AttentionService.java
@@ -64,10 +64,10 @@
     /** Attention is present. */
     public static final int ATTENTION_SUCCESS_PRESENT = 1;
 
-    /** Preempted by other camera user. */
+    /** Preempted by other client. */
     public static final int ATTENTION_FAILURE_PREEMPTED = 2;
 
-    /** Preempted by other camera user. */
+    /** Request timed out. */
     public static final int ATTENTION_FAILURE_TIMED_OUT = 3;
 
     /** Unknown reasons for failing to determine the attention. */
diff --git a/core/java/android/service/dreams/OWNERS b/core/java/android/service/dreams/OWNERS
index 3c9bbf8..426f002 100644
--- a/core/java/android/service/dreams/OWNERS
+++ b/core/java/android/service/dreams/OWNERS
@@ -1,3 +1,3 @@
-dsandler@google.com
+dsandler@android.com
 michaelwr@google.com
 roosa@google.com
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 1ddc099e..22104b5 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -33,6 +33,7 @@
     void onListenerConnected(in NotificationRankingUpdate update);
     void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder,
             in NotificationRankingUpdate update);
+    void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons);
     // stats only for assistant
     void onNotificationRemoved(in IStatusBarNotificationHolder notificationHolder,
             in NotificationRankingUpdate update, in NotificationStats stats, int reason);
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index c734b63..d4e8879 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -469,6 +469,17 @@
     }
 
     /**
+     * Implement this method to be notified when the behavior of silent notifications in the status
+     * bar changes. See {@link NotificationManager#shouldHideSilentStatusBarIcons()}.
+     *
+     * @param hideSilentStatusIcons whether or not status bar icons should be hidden for silent
+     *                              notifications
+     */
+    public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+        // optional
+    }
+
+    /**
      * Implement this method to learn about notification channel modifications.
      *
      * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
@@ -1411,6 +1422,12 @@
             mHandler.obtainMessage(
                     MyHandler.MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED, args).sendToTarget();
         }
+
+        @Override
+        public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+            mHandler.obtainMessage(MyHandler.MSG_ON_STATUS_BAR_ICON_BEHAVIOR_CHANGED,
+                    hideSilentStatusIcons).sendToTarget();
+        }
     }
 
     /**
@@ -2142,6 +2159,7 @@
         public static final int MSG_ON_INTERRUPTION_FILTER_CHANGED = 6;
         public static final int MSG_ON_NOTIFICATION_CHANNEL_MODIFIED = 7;
         public static final int MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED = 8;
+        public static final int MSG_ON_STATUS_BAR_ICON_BEHAVIOR_CHANGED = 9;
 
         public MyHandler(Looper looper) {
             super(looper, null, false);
@@ -2207,6 +2225,10 @@
                     int modificationType = (int) args.arg4;
                     onNotificationChannelGroupModified(pkgName, user, group, modificationType);
                 } break;
+
+                case MSG_ON_STATUS_BAR_ICON_BEHAVIOR_CHANGED: {
+                    onStatusBarIconsBehaviorChanged((Boolean) msg.obj);
+                } break;
             }
         }
     }
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 2789651..e76e096 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -16,7 +16,6 @@
 
 package android.service.voice;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
@@ -41,8 +40,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -80,33 +77,6 @@
      */
     public static final String SERVICE_META_DATA = "android.voice_interaction";
 
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = {"VOICE_STATE_"}, value = {
-            VOICE_STATE_NONE,
-            VOICE_STATE_CONDITIONAL_LISTENING,
-            VOICE_STATE_LISTENING,
-            VOICE_STATE_FULFILLING})
-    public @interface VoiceState {
-    }
-
-    /**
-     * Voice assistant inactive.
-     */
-    public static final int VOICE_STATE_NONE = 0;
-    /**
-     * Voice assistant listening, but will only trigger if it hears a request it can fulfill.
-     */
-    public static final int VOICE_STATE_CONDITIONAL_LISTENING = 1;
-    /**
-     * Voice assistant is listening to user speech.
-     */
-    public static final int VOICE_STATE_LISTENING = 2;
-    /**
-     * Voice assistant is fulfilling an action requested by the user.
-     */
-    public static final int VOICE_STATE_FULFILLING = 3;
-
     IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() {
         @Override
         public void ready() {
@@ -376,7 +346,7 @@
      *
      * @param state value indicating whether the assistant is listening, fulfilling, etc.
      */
-    public final void setVoiceState(@VoiceState int state) {
+    public final void setVoiceState(int state) {
         try {
             mSystemService.setVoiceState(state);
         } catch (RemoteException e) {
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index db9351b..2e8b7f0 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -57,6 +57,7 @@
         DEFAULT_FLAGS.put("settings_wifi_dpp", "true");
         DEFAULT_FLAGS.put("settings_wifi_mac_randomization", "true");
         DEFAULT_FLAGS.put("settings_wifi_sharing", "true");
+        DEFAULT_FLAGS.put("settings_mainline_module", "false");
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
         DEFAULT_FLAGS.put(SAFETY_HUB, "false");
         DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index dc7c343..6061cb2 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -399,10 +400,15 @@
     }
 
     private void initPrecompiledViews() {
-        // Check if precompiled layouts are enabled by a system property.
-        mUseCompiledView =
-            SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false);
+        initPrecompiledViews(
+                SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false));
+    }
+
+    private void initPrecompiledViews(boolean enablePrecompiledViews) {
+        mUseCompiledView = enablePrecompiledViews;
+
         if (!mUseCompiledView) {
+            mPrecompiledClassLoader = null;
             return;
         }
 
@@ -431,6 +437,17 @@
             }
             mUseCompiledView = false;
         }
+        if (!mUseCompiledView) {
+            mPrecompiledClassLoader = null;
+        }
+    }
+
+    /**
+     * @hide for use by CTS tests
+     */
+    @TestApi
+    public void setPrecompiledLayoutsEnabledForTesting(boolean enablePrecompiledLayouts) {
+        initPrecompiledViews(enablePrecompiledLayouts);
     }
 
     /**
diff --git a/core/java/android/view/textclassifier/ExtrasUtils.java b/core/java/android/view/textclassifier/ExtrasUtils.java
new file mode 100644
index 0000000..602455c
--- /dev/null
+++ b/core/java/android/view/textclassifier/ExtrasUtils.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2019 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.textclassifier;
+
+import android.annotation.Nullable;
+import android.app.RemoteAction;
+import android.content.Intent;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+
+/**
+ * Utility class for inserting and retrieving data in TextClassifier request/response extras.
+ * @hide
+ */
+public final class ExtrasUtils {
+
+    private static final String ACTIONS_INTENTS = "actions-intents";
+    private static final String FOREIGN_LANGUAGE = "foreign-language";
+    private static final String ENTITY_TYPE = "entity-type";
+    private static final String SCORE = "score";
+    private static final String MODEL_VERSION = "model-version";
+    private static final String MODEL_NAME = "model-name";
+
+    private ExtrasUtils() {}
+
+    /**
+     * Bundles and returns foreign language detection information for TextClassifier responses.
+     */
+    static Bundle createForeignLanguageExtra(
+            String language, float score, int modelVersion) {
+        final Bundle bundle = new Bundle();
+        bundle.putString(ENTITY_TYPE, language);
+        bundle.putFloat(SCORE, score);
+        bundle.putInt(MODEL_VERSION, modelVersion);
+        bundle.putString(MODEL_NAME, "langId_v" + modelVersion);
+        return bundle;
+    }
+
+    /**
+     * Stores {@code extra} as foreign language information in TextClassifier response object's
+     * extras {@code container}.
+     */
+    static void putForeignLanguageExtra(Bundle container, Bundle extra) {
+        container.putParcelable(FOREIGN_LANGUAGE, extra);
+    }
+
+    /**
+     * Returns foreign language detection information contained in the TextClassification object.
+     * responses.
+     */
+    @Nullable
+    public static Bundle getForeignLanguageExtra(TextClassification classification) {
+        return classification.getExtras().getBundle(FOREIGN_LANGUAGE);
+    }
+
+    /**
+     * Stores {@code actionIntents} information in TextClassifier response object's extras
+     * {@code container}.
+     */
+    static void putActionsIntents(Bundle container, ArrayList<Intent> actionsIntents) {
+        container.putParcelableArrayList(ACTIONS_INTENTS, actionsIntents);
+    }
+
+    /**
+     * Returns {@code actionIntents} information contained in the TextClassification object.
+     */
+    @Nullable
+    public static ArrayList<Intent> getActionsIntents(TextClassification classification) {
+        return classification.getExtras().getParcelableArrayList(ACTIONS_INTENTS);
+    }
+
+    /**
+     * Returns the first "translate" action found in the {@code classification} object.
+     */
+    @Nullable
+    public static RemoteAction findTranslateAction(TextClassification classification) {
+        final ArrayList<Intent> actionIntents = getActionsIntents(classification);
+        if (actionIntents != null) {
+            final int size = actionIntents.size();
+            for (int i = 0; i < size; i++) {
+                if (Intent.ACTION_TRANSLATE.equals(actionIntents.get(i).getAction())) {
+                    return classification.getActions().get(i);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the entity type contained in the {@code extra}.
+     */
+    @Nullable
+    public static String getEntityType(Bundle extra) {
+        return extra.getString(ENTITY_TYPE);
+    }
+
+    /**
+     * Returns the score contained in the {@code extra}.
+     */
+    @Nullable
+    public static float getScore(Bundle extra) {
+        return extra.getFloat(SCORE, -1);
+    }
+
+    /**
+     * Returns the model name contained in the {@code extra}.
+     */
+    @Nullable
+    public static String getModelName(Bundle extra) {
+        return extra.getString(MODEL_NAME);
+    }
+}
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index d9f7965..a059209 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -378,6 +378,8 @@
         @Nullable private OnClickListener mLegacyOnClickListener;
         @Nullable private String mId;
         @Nullable private Bundle mExtras;
+        @NonNull private final ArrayList<Intent> mActionIntents = new ArrayList<>();
+        @Nullable private Bundle mForeignLanguageExtra;
 
         /**
          * Sets the classified text.
@@ -412,8 +414,19 @@
          */
         @NonNull
         public Builder addAction(@NonNull RemoteAction action) {
+            return addAction(action, null);
+        }
+
+        /**
+         * @param intent the intent in the remote action.
+         * @see #addAction(RemoteAction)
+         * @hide
+         */
+        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+        public Builder addAction(RemoteAction action, @Nullable Intent intent) {
             Preconditions.checkArgument(action != null);
             mActions.add(action);
+            mActionIntents.add(intent);
             return this;
         }
 
@@ -499,13 +512,33 @@
         }
 
         /**
+         * @see #setExtras(Bundle)
+         * @hide
+         */
+        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+        public Builder setForeignLanguageExtra(@Nullable Bundle extra) {
+            mForeignLanguageExtra = extra;
+            return this;
+        }
+
+        /**
          * Builds and returns a {@link TextClassification} object.
          */
         @NonNull
         public TextClassification build() {
             return new TextClassification(mText, mLegacyIcon, mLegacyLabel, mLegacyIntent,
-                    mLegacyOnClickListener, mActions, mEntityConfidence, mId,
-                    mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
+                    mLegacyOnClickListener, mActions, mEntityConfidence, mId, buildExtras());
+        }
+
+        private Bundle buildExtras() {
+            final Bundle extras = mExtras == null ? new Bundle() : mExtras.deepCopy();
+            if (!mActionIntents.isEmpty()) {
+                ExtrasUtils.putActionsIntents(extras, mActionIntents);
+            }
+            if (mForeignLanguageExtra != null) {
+                ExtrasUtils.putForeignLanguageExtra(extras, mForeignLanguageExtra);
+            }
+            return extras.isEmpty() ? Bundle.EMPTY : extras;
         }
     }
 
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index 45668c0..ba1287f 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -71,10 +71,23 @@
 
     @Override
     public void onSelectionEvent(SelectionEvent event) {
-        checkDestroyed();
-        Preconditions.checkNotNull(event);
-        if (mEventHelper.sanitizeEvent(event)) {
-            mDelegate.onSelectionEvent(event);
+        try {
+            if (mEventHelper.sanitizeEvent(event)) {
+                mDelegate.onSelectionEvent(event);
+            }
+        } catch (Exception e) {
+            // Avoid crashing for event reporting.
+            Log.e(LOG_TAG, "Error reporting text classifier selection event", e);
+        }
+    }
+
+    @Override
+    public void onTextClassifierEvent(TextClassifierEvent event) {
+        try {
+            mDelegate.onTextClassifierEvent(event);
+        } catch (Exception e) {
+            // Avoid crashing for event reporting.
+            Log.e(LOG_TAG, "Error reporting text classifier event", e);
         }
     }
 
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 5a56136..e010155 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -161,12 +161,18 @@
      * No-op TextClassifier.
      * This may be used to turn off TextClassifier features.
      */
-    TextClassifier NO_OP = new TextClassifier() {};
+    TextClassifier NO_OP = new TextClassifier() {
+        @Override
+        public String toString() {
+            return "TextClassifier.NO_OP";
+        }
+    };
 
     /**
-     * Used as a boolean value to indicate the intent is generated by TextClassifier.
+     * Extra that is included on activity intents coming from a TextClassifier when
+     * it suggests actions to its caller.
      * <p>
-     * All {@link TextClassifier} implementations should set this boolean extra to be true in their
+     * All {@link TextClassifier} implementations should make sure this extra exists in their
      * generated intents.
      */
     String EXTRA_FROM_TEXT_CLASSIFIER = "android.view.textclassifier.extra.FROM_TEXT_CLASSIFIER";
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index cd13cc0..0d4338b 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -141,6 +141,8 @@
     @Nullable private final String mLanguage;
     private final float mScore;
 
+    @Nullable private final String mModelName;
+
     private TextClassifierEvent(
             int eventCategory,
             int eventType,
@@ -156,7 +158,8 @@
             int relativeSuggestedWordEndIndex,
             int[] actionIndex,
             String language,
-            float score) {
+            float score,
+            String modelVersion) {
         mEventCategory = eventCategory;
         mEventType = eventType;
         mEntityTypes = entityTypes;
@@ -172,6 +175,7 @@
         mActionIndices = actionIndex;
         mLanguage = language;
         mScore = score;
+        mModelName = modelVersion;
     }
 
     @Override
@@ -196,6 +200,7 @@
         dest.writeIntArray(mActionIndices);
         dest.writeString(mLanguage);
         dest.writeFloat(mScore);
+        dest.writeString(mModelName);
     }
 
     private static TextClassifierEvent readFromParcel(Parcel in) {
@@ -214,7 +219,8 @@
                 /* relativeSuggestedWordEndIndex= */ in.readInt(),
                 /* actionIndices= */ in.createIntArray(),
                 /* language= */ in.readString(),
-                /* score= */ in.readFloat());
+                /* score= */ in.readFloat(),
+                /* modelVersion= */ in.readString());
     }
 
     /**
@@ -264,6 +270,7 @@
         return mEventIndex;
     }
 
+    // TODO: Remove this API.
     /**
      * Returns the time this event occurred. This is the number of milliseconds since
      * January 1, 1970, 00:00:00 GMT. 0 indicates not set.
@@ -339,6 +346,15 @@
     }
 
     /**
+     * Returns the model name.
+     * @hide
+     */
+    @Nullable
+    public String getModelName() {
+        return mModelName;
+    }
+
+    /**
      * Builder to build a text classifier event.
      */
     public static final class Builder {
@@ -359,6 +375,8 @@
         @Nullable private String mLanguage;
         private float mScore;
 
+        private String mModelName;
+
         /**
          * Creates a builder for building {@link TextClassifierEvent}s.
          *
@@ -407,6 +425,7 @@
             return this;
         }
 
+        // TODO: Remove this API.
         /**
          * Sets the time this event occurred. This is the number of milliseconds since
          * January 1, 1970, 00:00:00 GMT. 0 indicates not set.
@@ -501,6 +520,15 @@
         }
 
         /**
+         * Sets the model name string.
+         * @hide
+         */
+        public Builder setModelName(@Nullable String modelVersion) {
+            mModelName = modelVersion;
+            return this;
+        }
+
+        /**
          * Builds and returns a text classifier event.
          */
         @NonNull
@@ -521,7 +549,8 @@
                     mRelativeSuggestedWordEndIndex,
                     mActionIndices,
                     mLanguage,
-                    mScore);
+                    mScore,
+                    mModelName);
         }
         // TODO: Add build(boolean validate).
     }
@@ -544,6 +573,7 @@
         out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
         out.append(", mLanguage=").append(mLanguage);
         out.append(", mScore=").append(mScore);
+        out.append(", mModelName=").append(mModelName);
         out.append("}");
         return out.toString();
     }
diff --git a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
index 5563dfc..6a12250 100644
--- a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
+++ b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
@@ -16,7 +16,6 @@
 package android.view.textclassifier;
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TEXTCLASSIFIER_MODEL;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TEXT_CLASSIFIER_EVENT_TIME;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TEXT_CLASSIFIER_FIRST_ENTITY_TYPE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TEXT_CLASSIFIER_SCORE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TEXT_CLASSIFIER_SECOND_ENTITY_TYPE;
@@ -46,7 +45,7 @@
     private final MetricsLogger mMetricsLogger;
 
     public TextClassifierEventTronLogger() {
-        mMetricsLogger = new MetricsLogger();
+        this(new MetricsLogger());
     }
 
     @VisibleForTesting
@@ -57,6 +56,7 @@
     /** Emits a text classifier event to the logs. */
     public void writeEvent(TextClassifierEvent event) {
         Preconditions.checkNotNull(event);
+
         int category = getCategory(event);
         if (category == -1) {
             Log.w(TAG, "Unknown category: " + event.getEventCategory());
@@ -65,14 +65,12 @@
         final LogMaker log = new LogMaker(category)
                 .setSubtype(getLogType(event))
                 .addTaggedData(FIELD_TEXT_CLASSIFIER_SESSION_ID, event.getResultId())
-                .addTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME, event.getEventTime())
-                .addTaggedData(FIELD_TEXTCLASSIFIER_MODEL,
-                        SelectionSessionLogger.SignatureParser.getModelName(event.getResultId()))
+                .addTaggedData(FIELD_TEXTCLASSIFIER_MODEL, getModelName(event))
                 .addTaggedData(FIELD_TEXT_CLASSIFIER_SCORE, event.getScore());
 
         String[] entityTypes = event.getEntityTypes();
-        // TRON does not support a field of list type, and thus workaround by store them
-        // in three separate fields. This is no longer an issue once we have moved to Westworld.
+        // The old logger does not support a field of list type, and thus workaround by store them
+        // in three separate fields. This is not an issue with the new logger.
         if (entityTypes.length >= 1) {
             log.addTaggedData(FIELD_TEXT_CLASSIFIER_FIRST_ENTITY_TYPE, entityTypes[0]);
         }
@@ -93,6 +91,13 @@
         debugLog(log);
     }
 
+    private static String getModelName(TextClassifierEvent event) {
+        if (event.getModelName() != null) {
+            return event.getModelName();
+        }
+        return SelectionSessionLogger.SignatureParser.getModelName(event.getResultId());
+    }
+
     private static int getCategory(TextClassifierEvent event) {
         switch (event.getEventCategory()) {
             case TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS:
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index c297928..14afa33 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -65,9 +65,6 @@
  */
 public final class TextClassifierImpl implements TextClassifier {
 
-    /** @hide */
-    public static final String ACTIONS_INTENTS = "actions-intents";
-
     private static final String LOG_TAG = DEFAULT_LOG_TAG;
 
     private static final boolean DEBUG = false;
@@ -343,7 +340,11 @@
         if (DEBUG) {
             Log.d(DEFAULT_LOG_TAG, "onTextClassifierEvent() called with: event = [" + event + "]");
         }
-        mTextClassifierEventTronLogger.writeEvent(event);
+        try {
+            mTextClassifierEventTronLogger.writeEvent(event);
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "Error writing event", e);
+        }
     }
 
     /** @inheritDoc */
@@ -566,12 +567,16 @@
         final float foreignTextThreshold = mSettings.getLangIdThresholdOverride() >= 0
                 ? mSettings.getLangIdThresholdOverride()
                 : 0.5f /* TODO: Load this from the langId model. */;
+        final Bundle foreignLanguageBundle =
+                detectForeignLanguage(classifiedText, foreignTextThreshold);
+        builder.setForeignLanguageExtra(foreignLanguageBundle);
+
         boolean isPrimaryAction = true;
         final ArrayList<Intent> sourceIntents = new ArrayList<>();
         List<LabeledIntent> labeledIntents = mIntentFactory.create(
                 mContext,
                 classifiedText,
-                isForeignText(classifiedText, foreignTextThreshold),
+                foreignLanguageBundle != null,
                 referenceTime,
                 highestScoringResult);
         for (LabeledIntent labeledIntent : labeledIntents) {
@@ -590,28 +595,28 @@
                                 labeledIntent.getIntent(), labeledIntent.getRequestCode())));
                 isPrimaryAction = false;
             }
-            builder.addAction(action);
-            sourceIntents.add(labeledIntent.getIntent());
+            builder.addAction(action, labeledIntent.getIntent());
         }
 
-        final Bundle extras = new Bundle();
-        extras.putParcelableArrayList(ACTIONS_INTENTS, sourceIntents);
-
-        return builder.setId(createId(text, start, end))
-                .setExtras(extras)
-                .build();
+        return builder.setId(createId(text, start, end)).build();
     }
 
-    private boolean isForeignText(String text, float threshold) {
+    /**
+     * Returns a bundle with the language and confidence score if it finds the text to be
+     * in a foreign language. Otherwise returns null.
+     */
+    @Nullable
+    private Bundle detectForeignLanguage(String text, float threshold) {
         if (threshold > 1) {
-            return false;
+            return null;
         }
 
         // TODO: Revisit this algorithm.
         try {
-            final LangIdModel.LanguageResult[] langResults = getLangIdImpl().detectLanguages(text);
+            final LangIdModel langId = getLangIdImpl();
+            final LangIdModel.LanguageResult[] langResults = langId.detectLanguages(text);
             if (langResults.length <= 0) {
-                return false;
+                return null;
             }
 
             LangIdModel.LanguageResult highestScoringResult = langResults[0];
@@ -621,7 +626,7 @@
                 }
             }
             if (highestScoringResult.getScore() < threshold) {
-                return false;
+                return null;
             }
             // TODO: Remove
             Log.d(LOG_TAG, String.format("Language detected: <%s:%s>",
@@ -632,14 +637,15 @@
             final int size = deviceLocales.size();
             for (int i = 0; i < size; i++) {
                 if (deviceLocales.get(i).getLanguage().equals(detected.getLanguage())) {
-                    return false;
+                    return null;
                 }
             }
-            return true;
+            return ExtrasUtils.createForeignLanguageExtra(
+                    detected.getLanguage(), highestScoringResult.getScore(), langId.getVersion());
         } catch (Throwable t) {
             Log.e(LOG_TAG, "Error detecting foreign text. Ignored.", t);
         }
-        return false;
+        return null;
     }
 
     @Override
@@ -773,3 +779,4 @@
         }
     }
 }
+
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index de1f3df..09aa066 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -163,7 +163,7 @@
                     TextUtils.join(",", Build.SUPPORTED_ABIS),
                     null, // instructionSet
                     Process.FIRST_ISOLATED_UID,
-                    Process.LAST_ISOLATED_UID);
+                    Integer.MAX_VALUE); // TODO(b/123615476) deal with user-id ranges properly
             ZygoteProcess.waitForConnectionToZygote(sZygote.getPrimarySocketAddress());
 
             if (sPackageOriginalAppInfo.sourceDir.equals(sPackage.applicationInfo.sourceDir)) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 4a60b6a..c38566b 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -4112,9 +4112,9 @@
             }
         }
 
-        private MenuItem addAssistMenuItem(Menu menu, RemoteAction action, int intemId, int order,
+        private MenuItem addAssistMenuItem(Menu menu, RemoteAction action, int itemId, int order,
                 int showAsAction) {
-            final MenuItem item = menu.add(TextView.ID_ASSIST, intemId, order, action.getTitle())
+            final MenuItem item = menu.add(TextView.ID_ASSIST, itemId, order, action.getTitle())
                     .setContentDescription(action.getContentDescription());
             if (action.shouldShowIcon()) {
                 item.setIcon(action.getIcon().loadDrawable(mTextView.getContext()));
@@ -4188,7 +4188,8 @@
 
         @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-            getSelectionActionModeHelper().onSelectionAction(item.getItemId());
+            getSelectionActionModeHelper()
+                    .onSelectionAction(item.getItemId(), item.getTitle().toString());
 
             if (mProcessTextIntentActionsHandler.performMenuItemAction(item)) {
                 return true;
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 4caf288..564cfdd 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -20,12 +20,14 @@
 import android.annotation.Nullable;
 import android.annotation.UiThread;
 import android.annotation.WorkerThread;
+import android.app.RemoteAction;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.os.AsyncTask;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.text.Layout;
 import android.text.Selection;
@@ -34,13 +36,16 @@
 import android.text.util.Linkify;
 import android.util.Log;
 import android.view.ActionMode;
+import android.view.textclassifier.ExtrasUtils;
 import android.view.textclassifier.SelectionEvent;
 import android.view.textclassifier.SelectionEvent.InvocationMethod;
 import android.view.textclassifier.SelectionSessionLogger;
 import android.view.textclassifier.TextClassification;
 import android.view.textclassifier.TextClassificationConstants;
+import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextClassifierEvent;
 import android.view.textclassifier.TextSelection;
 import android.widget.Editor.SelectionModifierCursorController;
 
@@ -166,16 +171,17 @@
         }
     }
 
-    public void onSelectionAction(int menuItemId) {
+    /** Reports a selection action event. */
+    public void onSelectionAction(int menuItemId, @Nullable String actionLabel) {
         mSelectionTracker.onSelectionAction(
                 mTextView.getSelectionStart(), mTextView.getSelectionEnd(),
-                getActionType(menuItemId), mTextClassification);
+                getActionType(menuItemId), actionLabel, mTextClassification);
     }
 
     public void onSelectionDrag() {
         mSelectionTracker.onSelectionAction(
                 mTextView.getSelectionStart(), mTextView.getSelectionEnd(),
-                SelectionEvent.ACTION_DRAG, mTextClassification);
+                SelectionEvent.ACTION_DRAG, /* actionLabel= */ null, mTextClassification);
     }
 
     public void onTextChanged(int start, int end) {
@@ -511,8 +517,11 @@
             mOriginalEnd = mSelectionEnd = selectionEnd;
             mAllowReset = false;
             maybeInvalidateLogger();
-            mLogger.logSelectionStarted(mTextView.getTextClassificationSession(),
-                    text, selectionStart,
+            mLogger.logSelectionStarted(
+                    mTextView.getTextClassificationSession(),
+                    mTextView.getTextClassificationContext(),
+                    text,
+                    selectionStart,
                     isLink ? SelectionEvent.INVOCATION_LINK : SelectionEvent.INVOCATION_MANUAL);
         }
 
@@ -570,10 +579,12 @@
         public void onSelectionAction(
                 int selectionStart, int selectionEnd,
                 @SelectionEvent.ActionType int action,
+                @Nullable String actionLabel,
                 @Nullable TextClassification classification) {
             if (isSelectionStarted()) {
                 mAllowReset = false;
-                mLogger.logSelectionAction(selectionStart, selectionEnd, action, classification);
+                mLogger.logSelectionAction(
+                        selectionStart, selectionEnd, action, actionLabel, classification);
             }
         }
 
@@ -596,7 +607,8 @@
                     mSelectionEnd = editor.getTextView().getSelectionEnd();
                     mLogger.logSelectionAction(
                             textView.getSelectionStart(), textView.getSelectionEnd(),
-                            SelectionEvent.ACTION_RESET, null /* classification */);
+                            SelectionEvent.ACTION_RESET,
+                            /* actionLabel= */ null, /* classification= */ null);
                 }
                 return selected;
             }
@@ -605,7 +617,9 @@
 
         public void onTextChanged(int start, int end, TextClassification classification) {
             if (isSelectionStarted() && start == mSelectionStart && end == mSelectionEnd) {
-                onSelectionAction(start, end, SelectionEvent.ACTION_OVERTYPE, classification);
+                onSelectionAction(
+                        start, end, SelectionEvent.ACTION_OVERTYPE,
+                        /* actionLabel= */ null, classification);
             }
         }
 
@@ -644,7 +658,8 @@
                 if (mIsPending) {
                     mLogger.logSelectionAction(
                             mSelectionStart, mSelectionEnd,
-                            SelectionEvent.ACTION_ABANDON, null /* classification */);
+                            SelectionEvent.ACTION_ABANDON,
+                            /* actionLabel= */ null, /* classification= */ null);
                     mSelectionStart = mSelectionEnd = -1;
                     mLogger.endTextClassificationSession();
                     mIsPending = false;
@@ -679,6 +694,11 @@
         private final BreakIterator mTokenIterator;
 
         @Nullable private TextClassifier mClassificationSession;
+        @Nullable private TextClassificationContext mClassificationContext;
+
+        @Nullable private TextClassifierEvent mTranslateViewEvent;
+        @Nullable private TextClassifierEvent mTranslateClickEvent;
+
         private int mStartIndex;
         private String mText;
 
@@ -690,6 +710,7 @@
 
         public void logSelectionStarted(
                 TextClassifier classificationSession,
+                TextClassificationContext classificationContext,
                 CharSequence text, int index,
                 @InvocationMethod int invocationMethod) {
             try {
@@ -701,6 +722,7 @@
                 mTokenIterator.setText(mText);
                 mStartIndex = index;
                 mClassificationSession = classificationSession;
+                mClassificationContext = classificationContext;
                 if (hasActiveClassificationSession()) {
                     mClassificationSession.onSelectionEvent(
                             SelectionEvent.createSelectionStartedEvent(invocationMethod, 0));
@@ -731,6 +753,7 @@
                                 SelectionEvent.createSelectionModifiedEvent(
                                         wordIndices[0], wordIndices[1]));
                     }
+                    maybeGenerateTranslateViewEvent(classification);
                 }
             } catch (Exception e) {
                 // Avoid crashes due to logging.
@@ -741,6 +764,7 @@
         public void logSelectionAction(
                 int start, int end,
                 @SelectionEvent.ActionType int action,
+                @Nullable String actionLabel,
                 @Nullable TextClassification classification) {
             try {
                 if (hasActiveClassificationSession()) {
@@ -757,6 +781,9 @@
                                 SelectionEvent.createSelectionActionEvent(
                                         wordIndices[0], wordIndices[1], action));
                     }
+
+                    maybeGenerateTranslateClickEvent(classification, actionLabel);
+
                     if (SelectionEvent.isTerminal(action)) {
                         endTextClassificationSession();
                     }
@@ -773,6 +800,7 @@
 
         public void endTextClassificationSession() {
             if (hasActiveClassificationSession()) {
+                maybeReportTranslateEvents();
                 mClassificationSession.destroy();
             }
         }
@@ -843,6 +871,78 @@
         private boolean isWhitespace(int start, int end) {
             return PATTERN_WHITESPACE.matcher(mText.substring(start, end)).matches();
         }
+
+        private void maybeGenerateTranslateViewEvent(@Nullable TextClassification classification) {
+            if (classification != null) {
+                final TextClassifierEvent event = generateTranslateEvent(
+                        TextClassifierEvent.TYPE_ACTIONS_SHOWN,
+                        classification, mClassificationContext, /* actionLabel= */null);
+                mTranslateViewEvent = (event != null) ? event : mTranslateViewEvent;
+            }
+        }
+
+        private void maybeGenerateTranslateClickEvent(
+                @Nullable TextClassification classification, String actionLabel) {
+            if (classification != null) {
+                mTranslateClickEvent = generateTranslateEvent(
+                        TextClassifierEvent.TYPE_SMART_ACTION,
+                        classification, mClassificationContext, actionLabel);
+            }
+        }
+
+        private void maybeReportTranslateEvents() {
+            // Translate view and click events should only be logged once per selection session.
+            if (mTranslateViewEvent != null) {
+                mClassificationSession.onTextClassifierEvent(mTranslateViewEvent);
+                mTranslateViewEvent = null;
+            }
+            if (mTranslateClickEvent != null) {
+                mClassificationSession.onTextClassifierEvent(mTranslateClickEvent);
+                mTranslateClickEvent = null;
+            }
+        }
+
+        @Nullable
+        private static TextClassifierEvent generateTranslateEvent(
+                int eventType, TextClassification classification,
+                TextClassificationContext classificationContext, @Nullable String actionLabel) {
+
+            // The platform attempts to log "views" and "clicks" of the "Translate" action.
+            // Views are logged if a user is presented with the translate action during a selection
+            // session.
+            // Clicks are logged if the user clicks on the translate action.
+            // The index of the translate action is also logged to indicate whether it might have
+            // been in the main panel or overflow panel of the selection toolbar.
+            // NOTE that the "views" metric may be flawed if a TextView removes the translate menu
+            // item via a custom action mode callback or does not show a selection menu item.
+
+            final RemoteAction translateAction = ExtrasUtils.findTranslateAction(classification);
+            if (translateAction == null) {
+                // No translate action present. Nothing to log. Exit.
+                return null;
+            }
+
+            if (eventType == TextClassifierEvent.TYPE_SMART_ACTION
+                    && !translateAction.getTitle().toString().equals(actionLabel)) {
+                // Clicked action is not a translate action. Nothing to log. Exit.
+                // Note that we don't expect an actionLabel for "view" events.
+                return null;
+            }
+
+            final Bundle foreignLanguageExtra = ExtrasUtils.getForeignLanguageExtra(classification);
+            final String language = ExtrasUtils.getEntityType(foreignLanguageExtra);
+            final float score = ExtrasUtils.getScore(foreignLanguageExtra);
+            final String model = ExtrasUtils.getModelName(foreignLanguageExtra);
+            return new TextClassifierEvent.Builder(
+                    TextClassifierEvent.CATEGORY_LANGUAGE_DETECTION, eventType)
+                    .setEventContext(classificationContext)
+                    .setResultId(classification.getId())
+                    .setEntityTypes(language)
+                    .setScore(score)
+                    .setActionIndices(classification.getActions().indexOf(translateAction))
+                    .setModelName(model)
+                    .build();
+        }
     }
 
     /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2b45c06..8029cf0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -456,6 +456,7 @@
 
     private TextClassifier mTextClassifier;
     private TextClassifier mTextClassificationSession;
+    private TextClassificationContext mTextClassificationContext;
 
     // A flag to prevent repeated movements from escaping the enclosing text view. The idea here is
     // that if a user is holding down a movement key to traverse text, we shouldn't also traverse
@@ -12068,16 +12069,15 @@
                 } else {
                     widgetType = TextClassifier.WIDGET_TYPE_UNSELECTABLE_TEXTVIEW;
                 }
-                final TextClassificationContext textClassificationContext =
-                        new TextClassificationContext.Builder(
-                                mContext.getPackageName(), widgetType)
-                                .build();
+                mTextClassificationContext = new TextClassificationContext.Builder(
+                        mContext.getPackageName(), widgetType)
+                        .build();
                 if (mTextClassifier != null) {
                     mTextClassificationSession = tcm.createTextClassificationSession(
-                            textClassificationContext, mTextClassifier);
+                            mTextClassificationContext, mTextClassifier);
                 } else {
                     mTextClassificationSession = tcm.createTextClassificationSession(
-                            textClassificationContext);
+                            mTextClassificationContext);
                 }
             } else {
                 mTextClassificationSession = TextClassifier.NO_OP;
@@ -12087,6 +12087,15 @@
     }
 
     /**
+     * Returns the {@link TextClassificationContext} for the current TextClassifier session.
+     * @see #getTextClassificationSession()
+     */
+    @Nullable
+    TextClassificationContext getTextClassificationContext() {
+        return mTextClassificationContext;
+    }
+
+    /**
      * Returns true if this TextView uses a no-op TextClassifier.
      */
     boolean usesNoOpTextClassifier() {
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index da8605e..65b974b 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -104,6 +104,7 @@
     public boolean allowBypass;
     public boolean allowIPv4;
     public boolean allowIPv6;
+    public boolean isMetered = true;
     public Network[] underlyingNetworks;
     public ProxyInfo proxyInfo;
 
@@ -165,6 +166,7 @@
         out.writeInt(allowBypass ? 1 : 0);
         out.writeInt(allowIPv4 ? 1 : 0);
         out.writeInt(allowIPv6 ? 1 : 0);
+        out.writeInt(isMetered ? 1 : 0);
         out.writeTypedArray(underlyingNetworks, flags);
         out.writeParcelable(proxyInfo, flags);
     }
@@ -191,6 +193,7 @@
             config.allowBypass = in.readInt() != 0;
             config.allowIPv4 = in.readInt() != 0;
             config.allowIPv6 = in.readInt() != 0;
+            config.isMetered = in.readInt() != 0;
             config.underlyingNetworks = in.createTypedArray(Network.CREATOR);
             config.proxyInfo = in.readParcelable(null);
             return config;
diff --git a/core/java/com/android/internal/os/ChildZygoteInit.java b/core/java/com/android/internal/os/ChildZygoteInit.java
index a052a3b..cc74863 100644
--- a/core/java/com/android/internal/os/ChildZygoteInit.java
+++ b/core/java/com/android/internal/os/ChildZygoteInit.java
@@ -98,9 +98,11 @@
             throw new RuntimeException("Passed in UID range is invalid, min > max.");
         }
 
-        // Verify the UIDs are in the isolated UID range, as that's the only thing that we should
-        // be forking right now
-        if (!Process.isIsolated(uidGidMin) || !Process.isIsolated(uidGidMax)) {
+        // Verify the UIDs at least do not include system UIDs; we can't easily verify there
+        // are just isolated UIDs in the range, because for the webview zygote, there is no
+        // single range that captures all possible isolated UIDs.
+        // TODO(b/123615476) narrow this down
+        if (uidGidMin < Process.FIRST_ISOLATED_UID) {
             throw new RuntimeException("Passed in UID range does not map to isolated processes.");
         }
 
diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS
new file mode 100644
index 0000000..9283105
--- /dev/null
+++ b/core/java/com/android/internal/os/OWNERS
@@ -0,0 +1 @@
+per-file ZygoteArguments.java,ZygoteConnection.java,ZygoteInit.java,Zygote.java,ZygoteServer.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index a365a56..86342c4 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -4,3 +4,6 @@
 
 # Connectivity
 per-file android_net_* = ek@google.com, lorenzo@google.com, satk@google.com
+
+# Zygote
+per-file com_android_inernal_os_Zygote.*,fd_utils.* = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
diff --git a/core/jni/android_media_AudioAttributes.cpp b/core/jni/android_media_AudioAttributes.cpp
index 4be4def..b87a34d 100644
--- a/core/jni/android_media_AudioAttributes.cpp
+++ b/core/jni/android_media_AudioAttributes.cpp
@@ -135,7 +135,7 @@
 {
     audio_attributes_t *aa = new (calloc(1, sizeof(audio_attributes_t)))
                 audio_attributes_t{AUDIO_ATTRIBUTES_INITIALIZER};
-    return UniqueAaPtr{aa, free};
+    return UniqueAaPtr{aa};
 }
 
 jint JNIAudioAttributeHelper::nativeFromJava(JNIEnv* env, jobject jAudioAttributes,
diff --git a/core/jni/android_media_AudioAttributes.h b/core/jni/android_media_AudioAttributes.h
index c558352..628f7e3 100644
--- a/core/jni/android_media_AudioAttributes.h
+++ b/core/jni/android_media_AudioAttributes.h
@@ -27,7 +27,11 @@
 class JNIAudioAttributeHelper
 {
 public:
-    using UniqueAaPtr = std::unique_ptr<audio_attributes_t, decltype(free)*>;
+    struct FreeDeleter {
+        void operator()(void *p) const { ::free(p); }
+    };
+
+    using UniqueAaPtr = std::unique_ptr<audio_attributes_t, FreeDeleter>;
 
     /**
      * @brief makeUnique helper to prevent leak
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index e64d2af..ee11b61 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -96,7 +96,7 @@
     return toJavaStringArray(env, cStrings);
 }
 
-static jint verify(JNIEnv* env, jobjectArray packageInfo, android::vintf::CheckFlags::Type checks) {
+static jint android_os_VintfObject_verify(JNIEnv* env, jclass, jobjectArray packageInfo) {
     std::vector<std::string> cPackageInfo;
     if (packageInfo) {
         size_t count = env->GetArrayLength(packageInfo);
@@ -109,18 +109,19 @@
         }
     }
     std::string error;
-    int32_t status = VintfObject::CheckCompatibility(cPackageInfo, &error, checks);
+    int32_t status = VintfObject::CheckCompatibility(cPackageInfo, &error);
     if (status)
         LOG(WARNING) << "VintfObject.verify() returns " << status << ": " << error;
     return status;
 }
 
-static jint android_os_VintfObject_verify(JNIEnv* env, jclass, jobjectArray packageInfo) {
-    return verify(env, packageInfo, ::android::vintf::CheckFlags::ENABLE_ALL_CHECKS);
-}
-
 static jint android_os_VintfObject_verifyWithoutAvb(JNIEnv* env, jclass) {
-    return verify(env, nullptr, ::android::vintf::CheckFlags::DISABLE_AVB_CHECK);
+    std::string error;
+    int32_t status = VintfObject::CheckCompatibility({}, &error,
+            ::android::vintf::CheckFlags::DISABLE_AVB_CHECK);
+    if (status)
+        LOG(WARNING) << "VintfObject.verifyWithoutAvb() returns " << status << ": " << error;
+    return status;
 }
 
 static jobjectArray android_os_VintfObject_getHalNamesAndVersions(JNIEnv* env, jclass) {
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 94a6734..f2f7304 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2189,4 +2189,9 @@
 
     // OPEN: Settings > System > Aware > Disable > Dialog
     DIALOG_AWARE_DISABLE = 1633;
+
+    // OPEN: Settings > Settings > Network & internet > Click Mobile network to land on page with
+    // details for a SIM/eSIM mobile network > Click edit icon to bring up a rename dialog.
+    // OS: Q
+    MOBILE_NETWORK_RENAME_DIALOG = 1642;
 }
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 712994b..a160451 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -230,8 +230,6 @@
     }
     optional Connectivity connectivity = 32;
 
-    reserved 145; // Used to be ContentCapture, which moved to DeviceConfig
-
     optional SettingProto contact_metadata_sync_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto contacts_database_wal_enabled = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
@@ -1039,5 +1037,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 149;
+    // Next tag = 145 then 149; // (145 was removed)
 }
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 67b0652..eb214ba 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -712,6 +712,9 @@
     <!-- Indicates that connected MAC randomization is supported on this device -->
     <bool translatable="false" name="config_wifi_connected_mac_randomization_supported">false</bool>
 
+    <!-- Indicates that wifi link probing is supported on this device -->
+    <bool translatable="false" name="config_wifi_link_probing_supported">false</bool>
+
     <!-- Flag indicating whether we should enable the automatic brightness.
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index ef3834c..baf7587 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -240,7 +240,7 @@
     <dimen name="notification_header_icon_size">18dp</dimen>
 
     <!-- size (width and height) of the icon in the notification header -->
-    <dimen name="notification_header_icon_size_ambient">20dp</dimen>
+    <dimen name="notification_header_icon_size_ambient">18dp</dimen>
 
     <!-- The margin before the start of the app name in the header. -->
     <dimen name="notification_header_app_name_margin_start">3dp</dimen>
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 79afe69..0dc54e0 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -374,7 +374,9 @@
     <style name="TextAppearance.DeviceDefault.Caption" parent="TextAppearance.Material.Caption">
         <item name="fontFamily">@string/config_bodyFontFamily</item>
     </style>
-    <style name="TextAppearance.DeviceDefault.ListItem" parent="TextAppearance.DeviceDefault.Subhead"/>
+    <style name="TextAppearance.DeviceDefault.ListItem" parent="TextAppearance.DeviceDefault.Subhead">
+        <item name="fontFamily">@string/config_headlineFontFamily</item>
+    </style>
     <style name="TextAppearance.DeviceDefault.ListItemSecondary" parent="TextAppearance.DeviceDefault.Body1"/>
 
     <!-- Preference Styles -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 54a3243..5400d94 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1910,6 +1910,7 @@
   <java-symbol type="bool" name="config_wifi_convert_apband_5ghz_to_any" />
   <java-symbol type="bool" name="config_wifi_local_only_hotspot_5ghz" />
   <java-symbol type="bool" name="config_wifi_connected_mac_randomization_supported" />
+  <java-symbol type="bool" name="config_wifi_link_probing_supported" />
   <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" />
   <java-symbol type="bool" name="config_wimaxEnabled" />
   <java-symbol type="bool" name="show_ongoing_ime_switcher" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index e32b412..f38abd7 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -525,6 +525,7 @@
                     Settings.Global.WIFI_LINK_SPEED_METRICS_ENABLED,
                     Settings.Global.WIFI_PNO_FREQUENCY_CULLING_ENABLED,
                     Settings.Global.WIFI_PNO_RECENCY_SORTING_ENABLED,
+                    Settings.Global.WIFI_LINK_PROBING_ENABLED,
                     Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
                     Settings.Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS,
                     Settings.Global.WIFI_NETWORK_SHOW_RSSI,
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index 5e58f82..582be9d 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -21,8 +21,10 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
+import android.app.RemoteAction;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.text.Spannable;
 import android.text.SpannableString;
@@ -246,25 +248,31 @@
     public void testClassifyText_foreignText() {
         LocaleList originalLocales = LocaleList.getDefault();
         LocaleList.setDefault(LocaleList.forLanguageTags("en"));
-        String foreignText = "これは日本語のテキストです";
+        String japaneseText = "これは日本語のテキストです";
 
         Context context = new FakeContextBuilder()
                 .setIntentComponent(Intent.ACTION_TRANSLATE, FakeContextBuilder.DEFAULT_COMPONENT)
                 .build();
         TextClassifier classifier = new TextClassifierImpl(context, TC_CONSTANTS);
         TextClassification.Request request = new TextClassification.Request.Builder(
-                foreignText, 0, foreignText.length())
+                japaneseText, 0, japaneseText.length())
                 .setDefaultLocales(LOCALES)
                 .build();
 
         TextClassification classification = classifier.classifyText(request);
+        RemoteAction translateAction = classification.getActions().get(0);
         assertEquals(1, classification.getActions().size());
         assertEquals(
                 context.getString(com.android.internal.R.string.translate),
-                classification.getActions().get(0).getTitle());
-        Intent intent = (Intent) classification.getExtras()
-                .getParcelableArrayList(TextClassifierImpl.ACTIONS_INTENTS).get(0);
+                translateAction.getTitle());
+
+        assertEquals(translateAction, ExtrasUtils.findTranslateAction(classification));
+        Intent intent = ExtrasUtils.getActionsIntents(classification).get(0);
         assertEquals(Intent.ACTION_TRANSLATE, intent.getAction());
+        Bundle foreignLanguageInfo = ExtrasUtils.getForeignLanguageExtra(classification);
+        assertEquals("ja", ExtrasUtils.getEntityType(foreignLanguageInfo));
+        assertTrue(ExtrasUtils.getScore(foreignLanguageInfo) >= 0);
+        assertTrue(ExtrasUtils.getScore(foreignLanguageInfo) <= 1);
 
         LocaleList.setDefault(originalLocales);
     }
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index a47ab87..bcac5fd 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -329,6 +329,7 @@
         <permission name="android.permission.USE_RESERVED_DISK"/>
         <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+        <permission name="android.permission.STATUS_BAR_SERVICE"/>
         <permission name="android.permission.REQUEST_INCIDENT_REPORT_APPROVAL"/>
     </privapp-permissions>
 
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 97cb2ec..f9e7dd1 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -21,7 +21,6 @@
 import android.annotation.ColorLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.content.res.ResourcesImpl;
@@ -1762,9 +1761,7 @@
      *         previously assigned color space.
      *
      * @param colorSpace to assign to the bitmap
-     * @hide
      */
-    @TestApi
     public void setColorSpace(@NonNull ColorSpace colorSpace) {
         checkRecycled("setColorSpace called on a recycled bitmap");
         if (colorSpace == null) {
@@ -1815,9 +1812,7 @@
      * @throws IllegalArgumentException if the color space encoded in the long
      *                                  is invalid or unknown.
      *
-     * @hide pending API approval
      */
-    @TestApi
     public void eraseColor(@ColorLong long c) {
         checkRecycled("Can't erase a recycled bitmap");
         if (!isMutable()) {
@@ -1864,9 +1859,7 @@
      * @throws IllegalArgumentException if x, y exceed the bitmap's bounds
      * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
      *
-     * @hide pending API approval
      */
-    @TestApi
     public Color getColor(int x, int y) {
         checkRecycled("Can't call getColor() on a recycled bitmap");
         checkHardware("unable to getColor(), "
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 7eee6f4..73442db 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -24,7 +24,6 @@
 import android.annotation.Nullable;
 import android.annotation.Px;
 import android.annotation.Size;
-import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontVariationAxis;
 import android.os.Build;
@@ -974,10 +973,7 @@
      * @see Color for APIs that help manipulate a color long.
      *
      * @return the paint's color (and alpha).
-     *
-     * @hide pending API approval
      */
-    @TestApi
     @ColorLong
     public long getColorLong() {
         return mColor;
@@ -1006,10 +1002,7 @@
      *      to set in the paint.
      * @throws IllegalArgumentException if the color space encoded in the long
      *      is invalid or unknown.
-     *
-     * @hide pending API approval
      */
-    @TestApi
     public void setColor(@ColorLong long color) {
         ColorSpace cs = Color.colorSpace(color);
         float r = Color.red(color);
@@ -1445,10 +1438,7 @@
      *
      * @throws IllegalArgumentException if the color space encoded in the long
      *      is invalid or unknown.
-     *
-     * @hide pending API approval
      */
-    @TestApi
     public void setShadowLayer(float radius, float dx, float dy, @ColorLong long shadowColor) {
         ColorSpace cs = Color.colorSpace(shadowColor);
         float r = Color.red(shadowColor);
@@ -1517,9 +1507,7 @@
      * Returns the color of the shadow layer.
      * @see #setShadowLayer(float,float,float,int)
      * @see #setShadowLayer(float,float,float,long)
-     * @hide pending API approval
      */
-    @TestApi
     public @ColorLong long getShadowLayerColorLong() {
         return mShadowLayerColor;
     }
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 6dc9d34..8594766 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -759,6 +759,8 @@
 void RecordingCanvas::reset(DisplayListData* dl, const SkIRect& bounds) {
     this->resetCanvas(bounds.right(), bounds.bottom());
     fDL = dl;
+    mClipMayBeComplex = false;
+    mSaveCount = mComplexSaveCount = 0;
 }
 
 sk_sp<SkSurface> RecordingCanvas::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
@@ -770,6 +772,7 @@
 }
 
 void RecordingCanvas::willSave() {
+    mSaveCount++;
     fDL->save();
 }
 SkCanvas::SaveLayerStrategy RecordingCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
@@ -778,6 +781,11 @@
     return SkCanvas::kNoLayer_SaveLayerStrategy;
 }
 void RecordingCanvas::willRestore() {
+    mSaveCount--;
+    if (mSaveCount < mComplexSaveCount) {
+        mClipMayBeComplex = false;
+        mComplexSaveCount = 0;
+    }
     fDL->restore();
 }
 
@@ -798,17 +806,27 @@
 
 void RecordingCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle style) {
     fDL->clipRect(rect, op, style == kSoft_ClipEdgeStyle);
+    if (!getTotalMatrix().isScaleTranslate()) {
+        setClipMayBeComplex();
+    }
     this->INHERITED::onClipRect(rect, op, style);
 }
 void RecordingCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle style) {
+    if (rrect.getType() > SkRRect::kRect_Type || !getTotalMatrix().isScaleTranslate()) {
+        setClipMayBeComplex();
+    }
     fDL->clipRRect(rrect, op, style == kSoft_ClipEdgeStyle);
     this->INHERITED::onClipRRect(rrect, op, style);
 }
 void RecordingCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle style) {
+    setClipMayBeComplex();
     fDL->clipPath(path, op, style == kSoft_ClipEdgeStyle);
     this->INHERITED::onClipPath(path, op, style);
 }
 void RecordingCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
+    if (region.isComplex() || !getTotalMatrix().isScaleTranslate()) {
+        setClipMayBeComplex();
+    }
     fDL->clipRegion(region, op);
     this->INHERITED::onClipRegion(region, op);
 }
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index caaef67..3a76ca1 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -203,10 +203,41 @@
 
     void drawVectorDrawable(VectorDrawableRoot* tree);
 
+    /**
+     * If "isClipMayBeComplex" returns false, it is guaranteed the current clip is a rectangle.
+     * If the return value is true, then clip may or may not be complex (there is no guarantee).
+     */
+    inline bool isClipMayBeComplex() { return mClipMayBeComplex; }
+
 private:
     typedef SkCanvasVirtualEnforcer<SkNoDrawCanvas> INHERITED;
 
+    inline void setClipMayBeComplex() {
+        if (!mClipMayBeComplex) {
+            mComplexSaveCount = mSaveCount;
+            mClipMayBeComplex = true;
+        }
+    }
+
     DisplayListData* fDL;
+
+    /**
+     * mClipMayBeComplex tracks if the current clip is a rectangle. This flag is used to promote
+     * FunctorDrawable to a layer, if it is clipped by a non-rect.
+     */
+    bool mClipMayBeComplex = false;
+
+    /**
+     * mSaveCount is the current level of our save tree.
+     */
+    int mSaveCount = 0;
+
+    /**
+     * mComplexSaveCount is the first save level, which has a complex clip. Every level below
+     * mComplexSaveCount is assumed to have a complex clip and every level above mComplexSaveCount
+     * is guaranteed to not be complex.
+     */
+    int mComplexSaveCount = 0;
 };
 
 }  // namespace uirenderer
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index ddb7e4e..e6710cc 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -151,6 +151,7 @@
         // parent may have already dictated that a descendant layer is needed
         bool functorsNeedLayer =
                 ancestorDictatesFunctorsNeedLayer
+                || CC_UNLIKELY(isClipMayBeComplex())
 
                 // Round rect clipping forces layer for functors
                 || CC_UNLIKELY(getOutline().willRoundRectClip()) ||
@@ -193,6 +194,12 @@
 
     bool isProjectionReceiver() const { return mPrimitiveFields.mProjectionReceiver; }
 
+    bool setClipMayBeComplex(bool isClipMayBeComplex) {
+        return RP_SET(mPrimitiveFields.mClipMayBeComplex, isClipMayBeComplex);
+    }
+
+    bool isClipMayBeComplex() const { return mPrimitiveFields.mClipMayBeComplex; }
+
     bool setStaticMatrix(const SkMatrix* matrix) {
         delete mStaticMatrix;
         if (matrix) {
@@ -563,6 +570,7 @@
         bool mProjectBackwards = false;
         bool mProjectionReceiver = false;
         bool mAllowForceDark = true;
+        bool mClipMayBeComplex = false;
         Rect mClipBounds;
         Outline mOutline;
         RevealClip mRevealClip;
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 230065c..29d5ef2 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -73,7 +73,6 @@
         RenderNode* childNode = child.getRenderNode();
         Matrix4 mat4(child.getRecordedMatrix());
         info.damageAccumulator->pushTransform(&mat4);
-        // TODO: a layer is needed if the canvas is rotated or has a non-rect clip
         info.hasBackwardProjectedNodes = false;
         childFn(childNode, observer, info, functorsNeedLayer);
         hasBackwardProjectedNodesSubtree |= info.hasBackwardProjectedNodes;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index d54275f..d945635 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -113,6 +113,10 @@
     // Record the child node. Drawable dtor will be invoked when mChildNodes deque is cleared.
     mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier);
     auto& renderNodeDrawable = mDisplayList->mChildNodes.back();
+    if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
+        // Put Vulkan WebViews with non-rectangular clips in a HW layer
+        renderNode->mutateStagingProperties().setClipMayBeComplex(mRecorder.isClipMayBeComplex());
+    }
     drawDrawable(&renderNodeDrawable);
 
     // use staging property, since recording on UI thread
@@ -138,10 +142,8 @@
 void SkiaRecordingCanvas::drawWebViewFunctor(int functor) {
     FunctorDrawable* functorDrawable;
     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
-        // TODO(cblume) use VkFunctorDrawable instead of VkInteropFunctorDrawable here when the
-        // interop is disabled.
         functorDrawable =
-                mDisplayList->allocateDrawable<VkInteropFunctorDrawable>(functor, asSkCanvas());
+                mDisplayList->allocateDrawable<VkFunctorDrawable>(functor, asSkCanvas());
     } else {
         functorDrawable = mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, asSkCanvas());
     }
diff --git a/libs/hwui/private/hwui/DrawVkInfo.h b/libs/hwui/private/hwui/DrawVkInfo.h
index abc4dbf..fb55f5c 100644
--- a/libs/hwui/private/hwui/DrawVkInfo.h
+++ b/libs/hwui/private/hwui/DrawVkInfo.h
@@ -29,7 +29,7 @@
   VkDevice device;
   VkQueue queue;
   uint32_t graphics_queue_index;
-  uint32_t instance_version;
+  uint32_t api_version;
   const char* const* enabled_instance_extension_names;
   uint32_t enabled_instance_extension_names_length;
   const char* const* enabled_device_extension_names;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 1e75202..582d51e 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -83,7 +83,6 @@
     mDevice = VK_NULL_HANDLE;
     mPhysicalDevice = VK_NULL_HANDLE;
     mInstance = VK_NULL_HANDLE;
-    mInstanceVersion = 0u;
     mInstanceExtensions.clear();
     mDeviceExtensions.clear();
     free_features_extensions_structs(mPhysicalDeviceFeatures2);
@@ -100,7 +99,7 @@
         0,                                  // applicationVersion
         "android framework",                // pEngineName
         0,                                  // engineVerison
-        VK_MAKE_VERSION(1, 1, 0),           // apiVersion
+        mAPIVersion,                        // apiVersion
     };
 
     {
@@ -377,8 +376,9 @@
     }
 
     GET_PROC(EnumerateInstanceVersion);
-    LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&mInstanceVersion));
-    LOG_ALWAYS_FATAL_IF(mInstanceVersion < VK_MAKE_VERSION(1, 1, 0));
+    uint32_t instanceVersion;
+    LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
+    LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));
 
     GrVkExtensions extensions;
     LOG_ALWAYS_FATAL_IF(!this->setupDevice(extensions, mPhysicalDeviceFeatures2));
@@ -398,7 +398,7 @@
     backendContext.fDevice = mDevice;
     backendContext.fQueue = mGraphicsQueue;
     backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
-    backendContext.fInstanceVersion = mInstanceVersion;
+    backendContext.fMaxAPIVersion = mAPIVersion;
     backendContext.fVkExtensions = &extensions;
     backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
     backendContext.fGetProc = std::move(getProc);
@@ -446,7 +446,7 @@
             .device = mDevice,
             .queue = mGraphicsQueue,
             .graphics_queue_index = mGraphicsQueueIndex,
-            .instance_version = mInstanceVersion,
+            .api_version = mAPIVersion,
             .enabled_instance_extension_names = mInstanceExtensions.data(),
             .enabled_instance_extension_names_length =
                     static_cast<uint32_t>(mInstanceExtensions.size()),
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index abe78ef..6426fe2 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -246,7 +246,7 @@
     VkCommandBuffer mDummyCB = VK_NULL_HANDLE;
 
     // Variables saved to populate VkFunctorInitParams.
-    uint32_t mInstanceVersion = 0u;
+    static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0);
     std::vector<const char*> mInstanceExtensions;
     std::vector<const char*> mDeviceExtensions;
     VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{};
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 59c6a0a..63b57d1 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -181,22 +181,14 @@
         "android.location.GPS_ENABLED_CHANGE";
 
     /**
-     * Broadcast intent action when the configured location providers
-     * change. For use with {@link #isProviderEnabled(String)}. If you're interacting with the
-     * {@link android.provider.Settings.Secure#LOCATION_MODE} API, use {@link #MODE_CHANGED_ACTION}
-     * instead.
+     * Broadcast intent action when the set of enabled location providers changes. To check the
+     * status of a provider, use {@link #isProviderEnabled(String)}.
      */
-    public static final String PROVIDERS_CHANGED_ACTION =
-        "android.location.PROVIDERS_CHANGED";
+    public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
 
     /**
-     * Broadcast intent action when {@link android.provider.Settings.Secure#LOCATION_MODE} changes.
-     * For use with the {@link android.provider.Settings.Secure#LOCATION_MODE} API.
-     * If you're interacting with {@link #isProviderEnabled(String)}, use
-     * {@link #PROVIDERS_CHANGED_ACTION} instead.
-     *
-     * In the future, there may be mode changes that do not result in
-     * {@link #PROVIDERS_CHANGED_ACTION} broadcasts.
+     * Broadcast intent action when the device location mode changes. To check the location mode,
+     * use {@link #isLocationEnabled()}.
      */
     public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
 
@@ -207,8 +199,10 @@
      * If you're interacting with {@link #isProviderEnabled(String)}, use
      * {@link #PROVIDERS_CHANGED_ACTION} instead.
      *
+     * @deprecated Do not use.
      * @hide
      */
+    @Deprecated
     public static final String MODE_CHANGING_ACTION = "com.android.settings.location.MODE_CHANGING";
 
     /**
@@ -299,7 +293,7 @@
             "com.android.settings.location.FOOTER_STRING";
 
     // Map from LocationListeners to their associated ListenerTransport objects
-    private HashMap<LocationListener,ListenerTransport> mListeners =
+    private final HashMap<LocationListener, ListenerTransport> mListeners =
         new HashMap<LocationListener,ListenerTransport>();
 
     private class ListenerTransport extends ILocationListener.Stub {
@@ -1264,39 +1258,20 @@
     }
 
     /**
-     * Returns the current enabled/disabled status of location
+     * Returns the current enabled/disabled state of location. To listen for changes, see
+     * {@link #MODE_CHANGED_ACTION}.
      *
-     * @return true if location is enabled. false if location is disabled.
+     * @return true if location is enabled and false if location is disabled.
      */
     public boolean isLocationEnabled() {
         return isLocationEnabledForUser(Process.myUserHandle());
     }
 
     /**
-     * Method for enabling or disabling location.
-     *
-     * @param enabled true to enable location. false to disable location
-     * @param userHandle the user to set
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(WRITE_SECURE_SETTINGS)
-    public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
-        Settings.Secure.putIntForUser(
-                mContext.getContentResolver(),
-                Settings.Secure.LOCATION_MODE,
-                enabled
-                        ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
-                        : Settings.Secure.LOCATION_MODE_OFF,
-                userHandle.getIdentifier());
-    }
-
-    /**
-     * Returns the current enabled/disabled status of location
+     * Returns the current enabled/disabled state of location.
      *
      * @param userHandle the user to query
-     * @return true location is enabled. false if location is disabled.
+     * @return true if location is enabled and false if location is disabled.
      *
      * @hide
      */
@@ -1310,19 +1285,32 @@
     }
 
     /**
-     * Returns the current enabled/disabled status of the given provider.
+     * Enables or disables the location setting.
      *
-     * <p>If the user has enabled this provider in the Settings menu, true
-     * is returned otherwise false is returned
+     * @param enabled true to enable location and false to disable location.
+     * @param userHandle the user to set
      *
-     * <p>Callers should instead use {@link #isLocationEnabled()}
-     * unless they depend on provider-specific APIs such as
-     * {@link #requestLocationUpdates(String, long, float, LocationListener)}.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(WRITE_SECURE_SETTINGS)
+    public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
+        Settings.Secure.putIntForUser(
+                mContext.getContentResolver(),
+                Settings.Secure.LOCATION_MODE,
+                enabled
+                        ? Settings.Secure.LOCATION_MODE_ON
+                        : Settings.Secure.LOCATION_MODE_OFF,
+                userHandle.getIdentifier());
+    }
+
+    /**
+     * Returns the current enabled/disabled status of the given provider. To listen for changes, see
+     * {@link #PROVIDERS_CHANGED_ACTION}.
      *
-     * <p>
-     * Before API version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this
-     * method would throw {@link SecurityException} if the location permissions
-     * were not sufficient to use the specified provider.
+     * Before API version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method would throw
+     * {@link SecurityException} if the location permissions were not sufficient to use the
+     * specified provider.
      *
      * @param provider the name of the provider
      * @return true if the provider exists and is enabled
@@ -1334,19 +1322,13 @@
     }
 
     /**
-     * Returns the current enabled/disabled status of the given provider and user.
+     * Returns the current enabled/disabled status of the given provider and user. Callers should
+     * prefer {@link #isLocationEnabledForUser(UserHandle)} unless they depend on provider-specific
+     * APIs.
      *
-     * <p>If the user has enabled this provider in the Settings menu, true
-     * is returned otherwise false is returned
-     *
-     * <p>Callers should instead use {@link #isLocationEnabled()}
-     * unless they depend on provider-specific APIs such as
-     * {@link #requestLocationUpdates(String, long, float, LocationListener)}.
-     *
-     * <p>
-     * Before API version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this
-     * method would throw {@link SecurityException} if the location permissions
-     * were not sufficient to use the specified provider.
+     * Before API version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method would throw
+     * {@link SecurityException} if the location permissions were not sufficient to use the
+     * specified provider.
      *
      * @param provider the name of the provider
      * @param userHandle the user to query
@@ -1367,12 +1349,14 @@
     }
 
     /**
-     * Method for enabling or disabling a single location provider.
+     * Method for enabling or disabling a single location provider. This method is deprecated and
+     * functions as a best effort. It should not be relied on in any meaningful sense as providers
+     * may no longer be enabled or disabled by clients.
      *
      * @param provider the name of the provider
      * @param enabled true to enable the provider. false to disable the provider
      * @param userHandle the user to set
-     * @return true if the value was set, false on database errors
+     * @return true if the value was set, false otherwise
      *
      * @throws IllegalArgumentException if provider is null
      * @deprecated Do not manipulate providers individually, use
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 3d0afb09..0480eab 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -683,6 +683,7 @@
                     request.setSmallestDisplacement(in.readFloat());
                     request.setHideFromAppOps(in.readInt() != 0);
                     request.setLowPowerMode(in.readInt() != 0);
+                    request.setLocationSettingsIgnored(in.readInt() != 0);
                     String provider = in.readString();
                     if (provider != null) request.setProvider(provider);
                     WorkSource workSource = in.readParcelable(null);
@@ -711,6 +712,7 @@
         parcel.writeFloat(mSmallestDisplacement);
         parcel.writeInt(mHideFromAppOps ? 1 : 0);
         parcel.writeInt(mLowPowerMode ? 1 : 0);
+        parcel.writeInt(mLocationSettingsIgnored ? 1 : 0);
         parcel.writeString(mProvider);
         parcel.writeParcelable(mWorkSource, 0);
     }
@@ -755,6 +757,9 @@
             s.append(" num=").append(mNumUpdates);
         }
         s.append(" lowPowerMode=").append(mLowPowerMode);
+        if (mLocationSettingsIgnored) {
+            s.append(" ignoreSettings");
+        }
         s.append(']');
         return s.toString();
     }
diff --git a/media/Android.bp b/media/Android.bp
index e7d5faf..d7b8dd2 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -1,30 +1,4 @@
 java_library {
-    name: "updatable-media1",
-
-    srcs: [
-        ":media1-srcs",
-        ":framework-media-annotation-srcs",
-    ],
-
-    aidl: {
-        export_include_dirs: [
-            "apex/java",
-        ],
-
-        // TODO: find out a way to include only the necessary aidl files instead of dirs.
-        include_dirs: [
-            "frameworks/base/core/java",
-            "frameworks/base/media/java",
-        ],
-    },
-
-    installable: true,
-
-    // Make sure that the implementaion only relies on SDK or system APIs.
-    sdk_version: "system_current",
-}
-
-java_library {
     name: "updatable-media",
 
     srcs: [
@@ -57,55 +31,12 @@
 filegroup {
     name: "media-srcs-without-aidls",
     srcs : [
-        ":media1-srcs-without-aidls",
         ":mediasession2-srcs-without-aidls",
         ":mediaplayer2-srcs",
     ],
 }
 
 filegroup {
-    name: "media1-srcs",
-    srcs: [
-        "apex/java/android/media/MediaDescription.java",
-        "apex/java/android/media/MediaParceledListSlice.java",
-        "apex/java/android/media/Rating.java",
-        "apex/java/android/media/VolumeProvider.java",
-        "apex/java/android/media/browse/MediaBrowser.java",
-        "apex/java/android/media/browse/MediaBrowserUtils.java",
-        "apex/java/android/media/session/ControllerCallbackLink.java",
-        "apex/java/android/media/session/ControllerLink.java",
-        "apex/java/android/media/session/ISession.aidl",
-        "apex/java/android/media/session/ISessionCallback.aidl",
-        "apex/java/android/media/session/ISessionController.aidl",
-        "apex/java/android/media/session/ISessionControllerCallback.aidl",
-        "apex/java/android/media/session/MediaController.java",
-        "apex/java/android/media/session/MediaSessionEngine.java",
-        "apex/java/android/media/session/MediaSessionProviderService.java",
-        "apex/java/android/media/session/PlaybackState.java",
-        "apex/java/android/media/session/SessionCallbackLink.java",
-        "apex/java/android/media/session/SessionLink.java",
-        "apex/java/android/service/media/IMediaBrowserService.aidl",
-        "apex/java/android/service/media/IMediaBrowserServiceCallbacks.aidl",
-        "apex/java/android/service/media/MediaBrowserService.java",
-    ],
-}
-
-filegroup {
-    name: "media1-srcs-without-aidls",
-    srcs: [
-        ":media1-srcs",
-    ],
-    exclude_srcs: [
-        "apex/java/android/media/session/ISession.aidl",
-        "apex/java/android/media/session/ISessionCallback.aidl",
-        "apex/java/android/media/session/ISessionController.aidl",
-        "apex/java/android/media/session/ISessionControllerCallback.aidl",
-        "apex/java/android/service/media/IMediaBrowserService.aidl",
-        "apex/java/android/service/media/IMediaBrowserServiceCallbacks.aidl",
-    ],
-}
-
-filegroup {
     name: "mediasession2-srcs",
     srcs: [
         "apex/java/android/media/Controller2Link.java",
diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java
index 1a1f6fb..0fd496b 100644
--- a/media/apex/java/android/media/MediaPlayer2.java
+++ b/media/apex/java/android/media/MediaPlayer2.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringDef;
+import android.annotation.TestApi;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
@@ -3667,53 +3668,66 @@
     }
 
     /**
-     * The status codes for {@link DrmEventCallback#onDrmPrepared} listener.
+     * A status code for {@link DrmEventCallback#onDrmPrepared} listener.
      * <p>
      *
      * DRM preparation has succeeded.
-     * @hide
      */
     public static final int PREPARE_DRM_STATUS_SUCCESS = 0;
 
     /**
+     * A status code for {@link DrmEventCallback#onDrmPrepared} listener.
+     * <p>
+     *
      * The device required DRM provisioning but couldn't reach the provisioning server.
-     * @hide
      */
     public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1;
 
     /**
+     * A status code for {@link DrmEventCallback#onDrmPrepared} listener.
+     * <p>
+     *
      * The device required DRM provisioning but the provisioning server denied the request.
-     * @hide
      */
     public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2;
 
     /**
+     * A status code for {@link DrmEventCallback#onDrmPrepared} listener.
+     * <p>
+     *
      * The DRM preparation has failed .
-     * @hide
      */
     public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3;
 
     /**
+     * A status code for {@link DrmEventCallback#onDrmPrepared} listener.
+     * <p>
+     *
      * The crypto scheme UUID is not supported by the device.
-     * @hide
      */
     public static final int PREPARE_DRM_STATUS_UNSUPPORTED_SCHEME = 4;
 
     /**
+     * A status code for {@link DrmEventCallback#onDrmPrepared} listener.
+     * <p>
+     *
      * The hardware resources are not available, due to being in use.
-     * @hide
      */
     public static final int PREPARE_DRM_STATUS_RESOURCE_BUSY = 5;
 
     /**
+     * A status code for {@link DrmEventCallback#onDrmPrepared} listener.
+     * <p>
+     *
      * Restoring persisted offline keys failed.
-     * @hide
      */
     public static final int PREPARE_DRM_STATUS_RESTORE_ERROR = 6;
 
     /**
+     * A status code for {@link DrmEventCallback#onDrmPrepared} listener.
+     * <p>
+     *
      * Error during key request/response exchange with license server.
-     * @hide
      */
     public static final int PREPARE_DRM_STATUS_KEY_EXCHANGE_ERROR = 7;
 
@@ -3758,6 +3772,7 @@
      * @throws IllegalStateException if called before being prepared
      * @hide
      */
+    @TestApi
     public DrmInfo getDrmInfo(@NonNull DataSourceDesc dsd) {
         final SourceInfo sourceInfo = getSourceInfo(dsd);
         if (sourceInfo != null) {
@@ -3814,6 +3829,7 @@
      * @hide
      */
     // This is an asynchronous call.
+    @TestApi
     public Object prepareDrm(@NonNull DataSourceDesc dsd, @NonNull UUID uuid) {
         return addTask(newPrepareDrmTask(dsd, uuid));
     }
@@ -3905,6 +3921,7 @@
      * @hide
      */
     // This is a synchronous call.
+    @TestApi
     public void releaseDrm(@NonNull DataSourceDesc dsd)
             throws NoDrmSchemeException {
         final SourceInfo sourceInfo = getSourceInfo(dsd);
@@ -3955,6 +3972,7 @@
      * @throws NoDrmSchemeException if there is no active DRM session
      * @hide
      */
+    @TestApi
     public MediaDrm.KeyRequest getDrmKeyRequest(
             @NonNull DataSourceDesc dsd,
             @Nullable byte[] keySetId, @Nullable byte[] initData,
@@ -3997,6 +4015,7 @@
      * @hide
      */
     // This is a synchronous call.
+    @TestApi
     public byte[] provideDrmKeyResponse(
             @NonNull DataSourceDesc dsd,
             @Nullable byte[] keySetId, @NonNull byte[] response)
@@ -4023,6 +4042,7 @@
      * @hide
      */
     // This is a synchronous call.
+    @TestApi
     public void restoreDrmKeys(
             @NonNull DataSourceDesc dsd,
             @NonNull byte[] keySetId)
@@ -4050,6 +4070,7 @@
      * @throws NoDrmSchemeException if there is no active DRM session
      * @hide
      */
+    @TestApi
     public String getDrmPropertyString(
             @NonNull DataSourceDesc dsd,
             @NonNull @MediaDrmStringProperty String propertyName)
@@ -4078,6 +4099,7 @@
      * @hide
      */
     // This is a synchronous call.
+    @TestApi
     public void setDrmPropertyString(
             @NonNull DataSourceDesc dsd,
             @NonNull @MediaDrmStringProperty String propertyName, @NonNull String value)
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index f756658..0c3d625 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -3314,7 +3314,7 @@
      */
     public void setAudioPresentation(@NonNull AudioPresentation presentation) {
         if (presentation == null) {
-            throw new IllegalArgumentException("audio presentation is null");
+            throw new NullPointerException("audio presentation is null");
         }
         native_setAudioPresentation(presentation.getPresentationId(), presentation.getProgramId());
     }
diff --git a/media/apex/java/android/media/MediaDescription.aidl b/media/java/android/media/MediaDescription.aidl
similarity index 100%
rename from media/apex/java/android/media/MediaDescription.aidl
rename to media/java/android/media/MediaDescription.aidl
diff --git a/media/apex/java/android/media/MediaDescription.java b/media/java/android/media/MediaDescription.java
similarity index 100%
rename from media/apex/java/android/media/MediaDescription.java
rename to media/java/android/media/MediaDescription.java
diff --git a/media/apex/java/android/media/MediaParceledListSlice.aidl b/media/java/android/media/MediaParceledListSlice.aidl
similarity index 100%
rename from media/apex/java/android/media/MediaParceledListSlice.aidl
rename to media/java/android/media/MediaParceledListSlice.aidl
diff --git a/media/apex/java/android/media/MediaParceledListSlice.java b/media/java/android/media/MediaParceledListSlice.java
similarity index 100%
rename from media/apex/java/android/media/MediaParceledListSlice.java
rename to media/java/android/media/MediaParceledListSlice.java
diff --git a/media/apex/java/android/media/Rating.aidl b/media/java/android/media/Rating.aidl
similarity index 100%
rename from media/apex/java/android/media/Rating.aidl
rename to media/java/android/media/Rating.aidl
diff --git a/media/apex/java/android/media/Rating.java b/media/java/android/media/Rating.java
similarity index 100%
rename from media/apex/java/android/media/Rating.java
rename to media/java/android/media/Rating.java
diff --git a/media/apex/java/android/media/VolumeProvider.java b/media/java/android/media/VolumeProvider.java
similarity index 100%
rename from media/apex/java/android/media/VolumeProvider.java
rename to media/java/android/media/VolumeProvider.java
diff --git a/media/apex/java/android/media/browse/MediaBrowser.aidl b/media/java/android/media/browse/MediaBrowser.aidl
similarity index 100%
rename from media/apex/java/android/media/browse/MediaBrowser.aidl
rename to media/java/android/media/browse/MediaBrowser.aidl
diff --git a/media/apex/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
similarity index 100%
rename from media/apex/java/android/media/browse/MediaBrowser.java
rename to media/java/android/media/browse/MediaBrowser.java
diff --git a/media/apex/java/android/media/browse/MediaBrowserUtils.java b/media/java/android/media/browse/MediaBrowserUtils.java
similarity index 100%
rename from media/apex/java/android/media/browse/MediaBrowserUtils.java
rename to media/java/android/media/browse/MediaBrowserUtils.java
diff --git a/media/apex/java/android/media/session/ControllerCallbackLink.aidl b/media/java/android/media/session/ControllerCallbackLink.aidl
similarity index 100%
rename from media/apex/java/android/media/session/ControllerCallbackLink.aidl
rename to media/java/android/media/session/ControllerCallbackLink.aidl
diff --git a/media/apex/java/android/media/session/ControllerCallbackLink.java b/media/java/android/media/session/ControllerCallbackLink.java
similarity index 100%
rename from media/apex/java/android/media/session/ControllerCallbackLink.java
rename to media/java/android/media/session/ControllerCallbackLink.java
diff --git a/media/apex/java/android/media/session/ControllerLink.aidl b/media/java/android/media/session/ControllerLink.aidl
similarity index 100%
rename from media/apex/java/android/media/session/ControllerLink.aidl
rename to media/java/android/media/session/ControllerLink.aidl
diff --git a/media/apex/java/android/media/session/ControllerLink.java b/media/java/android/media/session/ControllerLink.java
similarity index 100%
rename from media/apex/java/android/media/session/ControllerLink.java
rename to media/java/android/media/session/ControllerLink.java
diff --git a/media/apex/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
similarity index 100%
rename from media/apex/java/android/media/session/ISession.aidl
rename to media/java/android/media/session/ISession.aidl
diff --git a/media/apex/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
similarity index 100%
rename from media/apex/java/android/media/session/ISessionCallback.aidl
rename to media/java/android/media/session/ISessionCallback.aidl
diff --git a/media/apex/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
similarity index 100%
rename from media/apex/java/android/media/session/ISessionController.aidl
rename to media/java/android/media/session/ISessionController.aidl
diff --git a/media/apex/java/android/media/session/ISessionControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl
similarity index 100%
rename from media/apex/java/android/media/session/ISessionControllerCallback.aidl
rename to media/java/android/media/session/ISessionControllerCallback.aidl
diff --git a/media/apex/java/android/media/session/MediaController.aidl b/media/java/android/media/session/MediaController.aidl
similarity index 100%
rename from media/apex/java/android/media/session/MediaController.aidl
rename to media/java/android/media/session/MediaController.aidl
diff --git a/media/apex/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
similarity index 100%
rename from media/apex/java/android/media/session/MediaController.java
rename to media/java/android/media/session/MediaController.java
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index ca3346c..03627de 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -142,10 +142,9 @@
         MediaSessionManager manager = (MediaSessionManager) context
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
         try {
-            MediaSessionEngine.CallbackStub cbStub = new MediaSessionEngine.CallbackStub();
-            SessionCallbackLink cbLink = new SessionCallbackLink(context, cbStub);
+            SessionCallbackLink cbLink = new SessionCallbackLink(context);
             SessionLink sessionLink = manager.createSession(cbLink, tag);
-            mImpl = new MediaSessionEngine(context, sessionLink, cbLink, cbStub);
+            mImpl = new MediaSessionEngine(context, sessionLink, cbLink);
             mMaxBitmapSize = context.getResources().getDimensionPixelSize(
                     android.R.dimen.config_mediaMetadataBitmapMaxSize);
         } catch (RuntimeException e) {
diff --git a/media/apex/java/android/media/session/MediaSessionEngine.java b/media/java/android/media/session/MediaSessionEngine.java
similarity index 78%
rename from media/apex/java/android/media/session/MediaSessionEngine.java
rename to media/java/android/media/session/MediaSessionEngine.java
index 31714e1..7fea90d 100644
--- a/media/apex/java/android/media/session/MediaSessionEngine.java
+++ b/media/java/android/media/session/MediaSessionEngine.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -44,7 +43,6 @@
 import android.view.KeyEvent;
 import android.view.ViewConfiguration;
 
-import java.lang.ref.WeakReference;
 import java.util.List;
 import java.util.Objects;
 
@@ -60,10 +58,7 @@
     private final MediaSession.Token mSessionToken;
     private final MediaController mController;
     private final SessionLink mSessionLink;
-    private final SessionCallbackLink mCbLink;
 
-    // Do not change the name of mCallbackWrapper. Support lib accesses this by using reflection.
-    @UnsupportedAppUsage
     private CallbackMessageHandler mCallbackHandler;
     private VolumeProvider mVolumeProvider;
     private PlaybackState mPlaybackState;
@@ -78,14 +73,12 @@
      *
      * @param context The context to use to create the session.
      * @param sessionLink A session link for the binder of MediaSessionRecord
-     * @param cbStub A callback link that handles incoming command to {@link MediaSession.Callback}.
      */
     public MediaSessionEngine(@NonNull Context context, @NonNull SessionLink sessionLink,
-            @NonNull SessionCallbackLink cbLink, @NonNull CallbackStub cbStub) {
+            @NonNull SessionCallbackLink cbLink) {
         mSessionLink = sessionLink;
-        mCbLink = cbLink;
 
-        cbStub.setSessionImpl(this);
+        cbLink.setSessionEngine(this);
         mSessionToken = new MediaSession.Token(mSessionLink.getController());
         mController = new MediaController(context, mSessionToken);
     }
@@ -479,97 +472,97 @@
         }
     }
 
-    private void dispatchPrepare(RemoteUserInfo caller) {
+    void dispatchPrepare(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREPARE, null, null);
     }
 
-    private void dispatchPrepareFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
+    void dispatchPrepareFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras);
     }
 
-    private void dispatchPrepareFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
+    void dispatchPrepareFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras);
     }
 
-    private void dispatchPrepareFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
+    void dispatchPrepareFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_URI, uri, extras);
     }
 
-    private void dispatchPlay(RemoteUserInfo caller) {
+    void dispatchPlay(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_PLAY, null, null);
     }
 
-    private void dispatchPlayFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
+    void dispatchPlayFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras);
     }
 
-    private void dispatchPlayFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
+    void dispatchPlayFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras);
     }
 
-    private void dispatchPlayFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
+    void dispatchPlayFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PLAY_URI, uri, extras);
     }
 
-    private void dispatchSkipToItem(RemoteUserInfo caller, long id) {
+    void dispatchSkipToItem(RemoteUserInfo caller, long id) {
         postToCallback(caller, CallbackMessageHandler.MSG_SKIP_TO_ITEM, id, null);
     }
 
-    private void dispatchPause(RemoteUserInfo caller) {
+    void dispatchPause(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_PAUSE, null, null);
     }
 
-    private void dispatchStop(RemoteUserInfo caller) {
+    void dispatchStop(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_STOP, null, null);
     }
 
-    private void dispatchNext(RemoteUserInfo caller) {
+    void dispatchNext(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_NEXT, null, null);
     }
 
-    private void dispatchPrevious(RemoteUserInfo caller) {
+    void dispatchPrevious(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREVIOUS, null, null);
     }
 
-    private void dispatchFastForward(RemoteUserInfo caller) {
+    void dispatchFastForward(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_FAST_FORWARD, null, null);
     }
 
-    private void dispatchRewind(RemoteUserInfo caller) {
+    void dispatchRewind(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_REWIND, null, null);
     }
 
-    private void dispatchSeekTo(RemoteUserInfo caller, long pos) {
+    void dispatchSeekTo(RemoteUserInfo caller, long pos) {
         postToCallback(caller, CallbackMessageHandler.MSG_SEEK_TO, pos, null);
     }
 
-    private void dispatchRate(RemoteUserInfo caller, Rating rating) {
+    void dispatchRate(RemoteUserInfo caller, Rating rating) {
         postToCallback(caller, CallbackMessageHandler.MSG_RATE, rating, null);
     }
 
-    private void dispatchCustomAction(RemoteUserInfo caller, String action, Bundle args) {
+    void dispatchCustomAction(RemoteUserInfo caller, String action, Bundle args) {
         postToCallback(caller, CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args);
     }
 
-    private void dispatchMediaButton(RemoteUserInfo caller, Intent mediaButtonIntent) {
+    void dispatchMediaButton(RemoteUserInfo caller, Intent mediaButtonIntent) {
         postToCallback(caller, CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent, null);
     }
 
-    private void dispatchMediaButtonDelayed(RemoteUserInfo info, Intent mediaButtonIntent,
+    void dispatchMediaButtonDelayed(RemoteUserInfo info, Intent mediaButtonIntent,
             long delay) {
         postToCallbackDelayed(info, CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT,
                 mediaButtonIntent, null, delay);
     }
 
-    private void dispatchAdjustVolume(RemoteUserInfo caller, int direction) {
+    void dispatchAdjustVolume(RemoteUserInfo caller, int direction) {
         postToCallback(caller, CallbackMessageHandler.MSG_ADJUST_VOLUME, direction, null);
     }
 
-    private void dispatchSetVolumeTo(RemoteUserInfo caller, int volume) {
+    void dispatchSetVolumeTo(RemoteUserInfo caller, int volume) {
         postToCallback(caller, CallbackMessageHandler.MSG_SET_VOLUME, volume, null);
     }
 
-    private void dispatchCommand(RemoteUserInfo caller, String command, Bundle args,
+    void dispatchCommand(RemoteUserInfo caller, String command, Bundle args,
             ResultReceiver resultCb) {
         Command cmd = new Command(command, args, resultCb);
         postToCallback(caller, CallbackMessageHandler.MSG_COMMAND, cmd, null);
@@ -979,259 +972,7 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @SystemApi
-    public static final class CallbackStub extends SessionCallbackLink.CallbackStub {
-        private WeakReference<MediaSessionEngine> mSessionImpl;
-
-        private static RemoteUserInfo createRemoteUserInfo(String packageName, int pid, int uid) {
-            return new RemoteUserInfo(packageName, pid, uid);
-        }
-
-        public CallbackStub() {
-        }
-
-        @Override
-        public void onCommand(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String command, Bundle args, ResultReceiver cb) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchCommand(createRemoteUserInfo(packageName, pid, uid),
-                        command, args, cb);
-            }
-        }
-
-        @Override
-        public void onMediaButton(String packageName, int pid, int uid, Intent mediaButtonIntent,
-                int sequenceNumber, ResultReceiver cb) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            try {
-                if (sessionImpl != null) {
-                    sessionImpl.dispatchMediaButton(
-                            createRemoteUserInfo(packageName, pid, uid), mediaButtonIntent);
-                }
-            } finally {
-                if (cb != null) {
-                    cb.send(sequenceNumber, null);
-                }
-            }
-        }
-
-        @Override
-        public void onMediaButtonFromController(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, Intent mediaButtonIntent) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid),
-                        mediaButtonIntent);
-            }
-        }
-
-        @Override
-        public void onPrepare(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrepare(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onPrepareFromMediaId(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String mediaId,
-                Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrepareFromMediaId(
-                        createRemoteUserInfo(packageName, pid, uid), mediaId, extras);
-            }
-        }
-
-        @Override
-        public void onPrepareFromSearch(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String query,
-                Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrepareFromSearch(
-                        createRemoteUserInfo(packageName, pid, uid), query, extras);
-            }
-        }
-
-        @Override
-        public void onPrepareFromUri(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, Uri uri, Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrepareFromUri(
-                        createRemoteUserInfo(packageName, pid, uid), uri, extras);
-            }
-        }
-
-        @Override
-        public void onPlay(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPlay(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onPlayFromMediaId(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String mediaId,
-                Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPlayFromMediaId(
-                        createRemoteUserInfo(packageName, pid, uid), mediaId, extras);
-            }
-        }
-
-        @Override
-        public void onPlayFromSearch(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String query,
-                Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPlayFromSearch(
-                        createRemoteUserInfo(packageName, pid, uid), query, extras);
-            }
-        }
-
-        @Override
-        public void onPlayFromUri(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, Uri uri, Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPlayFromUri(
-                        createRemoteUserInfo(packageName, pid, uid), uri, extras);
-            }
-        }
-
-        @Override
-        public void onSkipToTrack(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, long id) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchSkipToItem(
-                        createRemoteUserInfo(packageName, pid, uid), id);
-            }
-        }
-
-        @Override
-        public void onPause(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPause(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onStop(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchStop(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onNext(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchNext(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onPrevious(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrevious(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onFastForward(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchFastForward(
-                        createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onRewind(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchRewind(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onSeekTo(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, long pos) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchSeekTo(
-                        createRemoteUserInfo(packageName, pid, uid), pos);
-            }
-        }
-
-        @Override
-        public void onRate(String packageName, int pid, int uid, ControllerCallbackLink caller,
-                Rating rating) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchRate(
-                        createRemoteUserInfo(packageName, pid, uid), rating);
-            }
-        }
-
-        @Override
-        public void onCustomAction(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String action, Bundle args) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchCustomAction(
-                        createRemoteUserInfo(packageName, pid, uid), action, args);
-            }
-        }
-
-        @Override
-        public void onAdjustVolume(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, int direction) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchAdjustVolume(
-                        createRemoteUserInfo(packageName, pid, uid), direction);
-            }
-        }
-
-        @Override
-        public void onSetVolumeTo(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, int value) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchSetVolumeTo(
-                        createRemoteUserInfo(packageName, pid, uid), value);
-            }
-        }
-
-        void setSessionImpl(MediaSessionEngine sessionImpl) {
-            mSessionImpl = new WeakReference<>(sessionImpl);
-        }
-    }
-
-    /**
+     /**
      * A single item that is part of the play queue. It contains a description
      * of the item and its id in the queue.
      */
diff --git a/media/apex/java/android/media/session/MediaSessionProviderService.java b/media/java/android/media/session/MediaSessionProviderService.java
similarity index 100%
rename from media/apex/java/android/media/session/MediaSessionProviderService.java
rename to media/java/android/media/session/MediaSessionProviderService.java
diff --git a/media/apex/java/android/media/session/PlaybackState.aidl b/media/java/android/media/session/PlaybackState.aidl
similarity index 100%
rename from media/apex/java/android/media/session/PlaybackState.aidl
rename to media/java/android/media/session/PlaybackState.aidl
diff --git a/media/apex/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
similarity index 100%
rename from media/apex/java/android/media/session/PlaybackState.java
rename to media/java/android/media/session/PlaybackState.java
diff --git a/media/apex/java/android/media/session/SessionCallbackLink.aidl b/media/java/android/media/session/SessionCallbackLink.aidl
similarity index 100%
rename from media/apex/java/android/media/session/SessionCallbackLink.aidl
rename to media/java/android/media/session/SessionCallbackLink.aidl
diff --git a/media/apex/java/android/media/session/SessionCallbackLink.java b/media/java/android/media/session/SessionCallbackLink.java
similarity index 79%
rename from media/apex/java/android/media/session/SessionCallbackLink.java
rename to media/java/android/media/session/SessionCallbackLink.java
index 3bcb65c..4c2918a 100644
--- a/media/apex/java/android/media/session/SessionCallbackLink.java
+++ b/media/java/android/media/session/SessionCallbackLink.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.media.Rating;
+import android.media.session.MediaSessionManager.RemoteUserInfo;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -35,6 +36,8 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 
+import java.lang.ref.WeakReference;
+
 /**
  * Handles incoming commands to {@link MediaSession.Callback}.
  * @hide
@@ -42,16 +45,15 @@
 @SystemApi
 public final class SessionCallbackLink implements Parcelable {
     final Context mContext;
-    final CallbackStub mCallbackStub;
     final ISessionCallback mISessionCallback;
 
     /**
      * Constructor for stub (Callee)
+     * @hide
      */
-    SessionCallbackLink(@NonNull Context context, @NonNull CallbackStub callbackStub) {
+    public SessionCallbackLink(@NonNull Context context) {
         mContext = context;
-        mCallbackStub = callbackStub;
-        mISessionCallback = new CallbackStubProxy();
+        mISessionCallback = new CallbackStub();
     }
 
     /**
@@ -59,11 +61,19 @@
      */
     public SessionCallbackLink(IBinder binder) {
         mContext = null;
-        mCallbackStub = null;
         mISessionCallback = ISessionCallback.Stub.asInterface(binder);
     }
 
     /**
+     * Set {@link MediaSessionEngine} which will be used by {@link CallbackStub}.
+     */
+    void setSessionEngine(@Nullable MediaSessionEngine sessionImpl) {
+        if (mISessionCallback instanceof CallbackStub) {
+            ((CallbackStub) mISessionCallback).mSessionImpl = new WeakReference<>(sessionImpl);
+        }
+    }
+
+    /**
      * Notify session that a controller sends a command.
      *
      * @param packageName the package name of the controller
@@ -540,139 +550,24 @@
                 }
             };
 
-    /**
-     * Class for Stub implementation
-     */
-    abstract static class CallbackStub {
-        /** Stub method for ISessionCallback.notifyCommand */
-        public void onCommand(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull String command,
-                @Nullable Bundle args, @Nullable ResultReceiver cb) {
+    private class CallbackStub extends ISessionCallback.Stub {
+        private WeakReference<MediaSessionEngine> mSessionImpl;
+
+        private RemoteUserInfo createRemoteUserInfo(String packageName, int pid, int uid) {
+            return new RemoteUserInfo(packageName, pid, uid);
         }
 
-        /** Stub method for ISessionCallback.notifyMediaButton */
-        public void onMediaButton(@NonNull String packageName, int pid, int uid,
-                @NonNull Intent mediaButtonIntent, int sequenceNumber,
-                @Nullable ResultReceiver cb) {
-        }
-
-        /** Stub method for ISessionCallback.notifyMediaButtonFromController */
-        public void onMediaButtonFromController(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull Intent mediaButtonIntent) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrepare */
-        public void onPrepare(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrepareFromMediaId */
-        public void onPrepareFromMediaId(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
-                @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrepareFromSearch */
-        public void onPrepareFromSearch(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, String query, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrepareFromUri */
-        public void onPrepareFromUri(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull Uri uri, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPlay */
-        public void onPlay(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPlayFromMediaId */
-        public void onPlayFromMediaId(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
-                @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPlayFromSearch */
-        public void onPlayFromSearch(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, String query, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPlayFromUri */
-        public void onPlayFromUri(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull Uri uri, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifySkipToTrack */
-        public void onSkipToTrack(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, long id) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPause */
-        public void onPause(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyStop */
-        public void onStop(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyNext */
-        public void onNext(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrevious */
-        public void onPrevious(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyFastForward */
-        public void onFastForward(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyRewind */
-        public void onRewind(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifySeekTo */
-        public void onSeekTo(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, long pos) {
-        }
-
-        /** Stub method for ISessionCallback.notifyRate */
-        public void onRate(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull Rating rating) {
-        }
-
-        /** Stub method for ISessionCallback.notifyCustomAction */
-        public void onCustomAction(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull String action,
-                @Nullable Bundle args) {
-        }
-
-        /** Stub method for ISessionCallback.notifyAdjustVolume */
-        public void onAdjustVolume(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, int direction) {
-        }
-
-        /** Stub method for ISessionCallback.notifySetVolumeTo */
-        public void onSetVolumeTo(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, int value) {
-        }
-    }
-
-    private class CallbackStubProxy extends ISessionCallback.Stub {
         @Override
         public void notifyCommand(String packageName, int pid, int uid,
                 ControllerCallbackLink caller, String command, Bundle args, ResultReceiver cb) {
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onCommand(packageName, pid, uid, caller, command, args, cb);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchCommand(createRemoteUserInfo(packageName, pid, uid),
+                            command, args, cb);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -684,9 +579,15 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onMediaButton(packageName, pid, uid, mediaButtonIntent,
-                        sequenceNumber, cb);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchMediaButton(
+                            createRemoteUserInfo(packageName, pid, uid), mediaButtonIntent);
+                }
             } finally {
+                if (cb != null) {
+                    cb.send(sequenceNumber, null);
+                }
                 Binder.restoreCallingIdentity(token);
             }
         }
@@ -697,8 +598,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onMediaButtonFromController(packageName, pid, uid, caller,
-                        mediaButtonIntent);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid),
+                            mediaButtonIntent);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -710,7 +614,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrepare(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrepare(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -722,7 +629,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrepareFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrepareFromMediaId(
+                            createRemoteUserInfo(packageName, pid, uid), mediaId, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -734,7 +645,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrepareFromSearch(packageName, pid, uid, caller, query, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrepareFromSearch(
+                            createRemoteUserInfo(packageName, pid, uid), query, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -746,7 +661,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrepareFromUri(packageName, pid, uid, caller, uri, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrepareFromUri(
+                            createRemoteUserInfo(packageName, pid, uid), uri, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -758,7 +677,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPlay(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPlay(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -770,7 +692,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPlayFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPlayFromMediaId(
+                            createRemoteUserInfo(packageName, pid, uid), mediaId, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -782,7 +708,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPlayFromSearch(packageName, pid, uid, caller, query, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPlayFromSearch(
+                            createRemoteUserInfo(packageName, pid, uid), query, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -794,7 +724,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPlayFromUri(packageName, pid, uid, caller, uri, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPlayFromUri(
+                            createRemoteUserInfo(packageName, pid, uid), uri, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -806,7 +740,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onSkipToTrack(packageName, pid, uid, caller, id);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchSkipToItem(
+                            createRemoteUserInfo(packageName, pid, uid), id);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -818,7 +756,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPause(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPause(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -830,7 +771,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onStop(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchStop(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -842,7 +786,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onNext(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchNext(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -854,7 +801,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrevious(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrevious(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -866,7 +816,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onFastForward(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchFastForward(
+                            createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -878,7 +832,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onRewind(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchRewind(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -890,7 +847,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onSeekTo(packageName, pid, uid, caller, pos);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchSeekTo(
+                            createRemoteUserInfo(packageName, pid, uid), pos);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -902,7 +863,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onRate(packageName, pid, uid, caller, rating);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchRate(
+                            createRemoteUserInfo(packageName, pid, uid), rating);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -913,7 +878,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onCustomAction(packageName, pid, uid, caller, action, args);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchCustomAction(
+                            createRemoteUserInfo(packageName, pid, uid), action, args);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -925,7 +894,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onAdjustVolume(packageName, pid, uid, caller, direction);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchAdjustVolume(
+                            createRemoteUserInfo(packageName, pid, uid), direction);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -937,7 +910,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onSetVolumeTo(packageName, pid, uid, caller, value);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchSetVolumeTo(
+                            createRemoteUserInfo(packageName, pid, uid), value);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/media/apex/java/android/media/session/SessionLink.aidl b/media/java/android/media/session/SessionLink.aidl
similarity index 100%
rename from media/apex/java/android/media/session/SessionLink.aidl
rename to media/java/android/media/session/SessionLink.aidl
diff --git a/media/apex/java/android/media/session/SessionLink.java b/media/java/android/media/session/SessionLink.java
similarity index 100%
rename from media/apex/java/android/media/session/SessionLink.java
rename to media/java/android/media/session/SessionLink.java
diff --git a/media/apex/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
similarity index 100%
rename from media/apex/java/android/service/media/IMediaBrowserService.aidl
rename to media/java/android/service/media/IMediaBrowserService.aidl
diff --git a/media/apex/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
similarity index 100%
rename from media/apex/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
rename to media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
diff --git a/media/apex/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
similarity index 100%
rename from media/apex/java/android/service/media/MediaBrowserService.java
rename to media/java/android/service/media/MediaBrowserService.java
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 81fce8a..866325c 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -426,6 +426,9 @@
     if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
         jniThrowException(env, "java/lang/IllegalArgumentException", msg);
         return true;
+    } else if (err == ERROR_UNSUPPORTED) {
+        jniThrowException(env, "java/lang/UnsupportedOperationException", msg);
+        return true;
     } else if (err == ERROR_DRM_NOT_PROVISIONED) {
         jniThrowException(env, "android/media/NotProvisionedException", msg);
         return true;
@@ -542,15 +545,15 @@
 
 
 // static
-bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
-                                   DrmPlugin::SecurityLevel securityLevel) {
+status_t JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
+                                       DrmPlugin::SecurityLevel securityLevel, bool *isSupported) {
     sp<IDrm> drm = MakeDrm();
 
     if (drm == NULL) {
-        return false;
+        return BAD_VALUE;
     }
 
-    return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel);
+    return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel, isSupported);
 }
 
 status_t JDrm::initCheck() const {
@@ -977,7 +980,14 @@
     }
     DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
 
-    return JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType, securityLevel);
+    bool isSupported;
+    status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
+            securityLevel, &isSupported);
+
+    if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) {
+        return false;
+    }
+    return isSupported;
 }
 
 static jbyteArray android_media_MediaDrm_openSession(
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index 9338861..5ebac1d 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -37,9 +37,10 @@
 };
 
 struct JDrm : public BnDrmClient {
-    static bool IsCryptoSchemeSupported(const uint8_t uuid[16],
-                                        const String8 &mimeType,
-                                        DrmPlugin::SecurityLevel level);
+    static status_t IsCryptoSchemeSupported(const uint8_t uuid[16],
+                                            const String8 &mimeType,
+                                            DrmPlugin::SecurityLevel level,
+                                            bool *isSupported);
 
     JDrm(JNIEnv *env, jobject thiz, const uint8_t uuid[16], const String8 &appPackageName);
 
diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h
index e31ce19..5b3e496 100644
--- a/native/webview/plat_support/draw_fn.h
+++ b/native/webview/plat_support/draw_fn.h
@@ -84,7 +84,7 @@
   VkDevice device;
   VkQueue queue;
   uint32_t graphics_queue_index;
-  uint32_t instance_version;
+  uint32_t api_version;
   const char* const* enabled_instance_extension_names;
   uint32_t enabled_instance_extension_names_length;
   const char* const* enabled_device_extension_names;
diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp
index afe103a..e43a60c 100644
--- a/native/webview/plat_support/draw_functor.cpp
+++ b/native/webview/plat_support/draw_functor.cpp
@@ -102,7 +102,7 @@
       .device = init_vk_params.device,
       .queue = init_vk_params.queue,
       .graphics_queue_index = init_vk_params.graphics_queue_index,
-      .instance_version = init_vk_params.instance_version,
+      .api_version = init_vk_params.api_version,
       .enabled_instance_extension_names =
           init_vk_params.enabled_instance_extension_names,
       .enabled_instance_extension_names_length =
@@ -177,9 +177,6 @@
         webview_functor_callbacks.vk.initialize = &initializeVk;
         webview_functor_callbacks.vk.draw = &drawVk;
         webview_functor_callbacks.vk.postDraw = &postDrawVk;
-        // TODO(boliu): Remove this once SkiaRecordingCanvas::drawWebViewFunctor
-        // no longer uses GL interop.
-        webview_functor_callbacks.gles.draw = &draw_gl;
         break;
     }
     callbacks_initialized = true;
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 7eaf04b..0a571c5 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -60,7 +60,6 @@
 
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import java.io.IOException;
@@ -107,11 +106,11 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
         logMetricsEvent(MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
 
         mCm = ConnectivityManager.from(this);
         mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
-        mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
         mUserAgent =
                 getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
         mUrl = getUrl();
@@ -637,7 +636,7 @@
     }
 
     private void logMetricsEvent(int event) {
-        MetricsLogger.action(this, event, getPackageName());
+        mCaptivePortal.logEvent(event, getPackageName());
     }
 
     private static final SparseArray<String> SSL_ERRORS = new SparseArray<>();
diff --git a/packages/CarSystemUI/res/values/integers_car.xml b/packages/CarSystemUI/res/values/integers_car.xml
index 777283d..be2cb0d8 100644
--- a/packages/CarSystemUI/res/values/integers_car.xml
+++ b/packages/CarSystemUI/res/values/integers_car.xml
@@ -23,7 +23,7 @@
     <!-- Number of milliseconds user can spend driving with the keyguard up. After that, we switch to Guest. -->
     <!-- If the number is negative, the feature is disabled.
          If it's zero, we switch to guest immediately as we start driving. -->
-    <integer name="driving_on_keyguard_timeout_ms">30000</integer>
+    <integer name="driving_on_keyguard_timeout_ms">-1</integer>
 
     <!--Percentage of the screen height, from the bottom, that a notification panel being
     partially closed at will result in it remaining open if released-->
diff --git a/packages/ExtServices/Android.bp b/packages/ExtServices/Android.bp
new file mode 100644
index 0000000..77972fe
--- /dev/null
+++ b/packages/ExtServices/Android.bp
@@ -0,0 +1,11 @@
+android_library {
+    name: "ExtServices-core",
+     srcs: [
+         "src/**/*.java",
+     ],
+     resource_dirs: [
+         "res",
+     ],
+
+     manifest: "AndroidManifest.xml",
+}
\ No newline at end of file
diff --git a/packages/ExtServices/tests/Android.bp b/packages/ExtServices/tests/Android.bp
new file mode 100644
index 0000000..5de4548
--- /dev/null
+++ b/packages/ExtServices/tests/Android.bp
@@ -0,0 +1,26 @@
+android_test {
+    name: "ExtServicesUnitTests",
+
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+
+    // We only want this apk build for tests.
+    certificate: "platform",
+
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+
+    static_libs: [
+        "ExtServices-core",
+        "android-support-test",
+        "mockito-target-minus-junit4",
+        "espresso-core",
+        "truth-prebuilt",
+        "testables",
+        "testng",
+    ],
+
+    platform_apis: true,
+}
\ No newline at end of file
diff --git a/packages/ExtServices/tests/Android.mk b/packages/ExtServices/tests/Android.mk
deleted file mode 100644
index a57fa94..0000000
--- a/packages/ExtServices/tests/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
-    mockito-target-minus-junit4 \
-    espresso-core \
-    truth-prebuilt \
-    testables \
-    testng
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := ExtServicesUnitTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_INSTRUMENTATION_FOR := ExtServices
-
-include $(BUILD_PACKAGE)
diff --git a/packages/ExtServices/tests/AndroidManifest.xml b/packages/ExtServices/tests/AndroidManifest.xml
index ddf725b..3cf1527 100644
--- a/packages/ExtServices/tests/AndroidManifest.xml
+++ b/packages/ExtServices/tests/AndroidManifest.xml
@@ -24,7 +24,7 @@
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="android.ext.services"
+                     android:targetPackage="android.ext.services.tests.unit"
                      android:label="ExtServices Test Cases">
     </instrumentation>
 
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/NotificationCategorizerTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationCategorizerTest.java
index 12908e6..c59885e 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/NotificationCategorizerTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationCategorizerTest.java
@@ -180,7 +180,7 @@
         assertFalse(nc.shouldSilence(NotificationCategorizer.CATEGORY_SYSTEM));
 
         when(mSbn.getUid()).thenReturn(FIRST_APPLICATION_UID);
-        assertEquals(NotificationCategorizer.CATEGORY_EVERYTHING_ELSE, nc.getCategory(mEntry));
+        assertEquals(NotificationCategorizer.CATEGORY_HIGH, nc.getCategory(mEntry));
     }
 
     @Test
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index f21561f..b34efc4 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -687,6 +687,15 @@
                                     }
                                     sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
                                 }
+
+                                @Override
+                                public void logEvent(int eventId, String packageName)
+                                        throws RemoteException {
+                                    mContext.enforceCallingPermission(
+                                            android.Manifest.permission.CONNECTIVITY_INTERNAL,
+                                            "CaptivePortal");
+                                    mCallback.logCaptivePortalLoginEvent(eventId, packageName);
+                                }
                             }));
                     final CaptivePortalProbeResult probeRes = mLastPortalProbeResult;
                     intent.putExtra(EXTRA_CAPTIVE_PORTAL_URL, probeRes.detectUrl);
diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS
index d188c65..d879087 100644
--- a/packages/SettingsLib/OWNERS
+++ b/packages/SettingsLib/OWNERS
@@ -4,7 +4,7 @@
 dehboxturtle@google.com
 dhnishi@google.com
 dling@google.com
-dsandler@google.com
+dsandler@android.com
 evanlaird@google.com
 jackqdyulei@google.com
 jmonk@google.com
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index ec70f8c..191bd8f 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -106,7 +106,7 @@
     <!-- Status message of Wi-Fi when network has matching passpoint credentials. [CHAR LIMIT=NONE] -->
     <string name="available_via_passpoint">Available via %1$s</string>
     <!-- Status message of OSU Provider network when not connected. [CHAR LIMIT=NONE] -->
-    <string name="tap_to_set_up">Tap to set up</string>
+    <string name="tap_to_sign_up">Tap to sign up</string>
     <!-- Package name for Settings app-->
     <string name="settings_package" translatable="false">com.android.settings</string>
     <!-- Package name for Certinstaller app-->
@@ -129,78 +129,16 @@
     <!-- Status message of Wi-Fi when an available network is a carrier network. [CHAR LIMIT=NONE] -->
     <string name="available_via_carrier">Available via %1$s</string>
 
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_AP_CONNECTION. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_ap_connection">Connection failed</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SERVER_URL_INVALID. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_server_url_invalid">Invalid OSU server URL</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SERVER_CONNECTION. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_server_connection">OSU server connection failed</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SERVER_VALIDATION. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_server_validation">OSU server validation failed</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_service_provider_verification">Invalid OSU server certificate</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_PROVISIONING_ABORTED. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_provisioning_aborted">Provisioning aborted</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_PROVISIONING_NOT_AVAILABLE. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_provisioning_not_available">Provisioning not available</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_INVALID_SERVER_URL. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_invalid_server_url">Invalid OSU server URL</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_UNEXPECTED_COMMAND_TYPE. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_unexpected_command_type">Unexpected command type</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_unexpected_soap_message_type">Unexpected SOAP message type</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SOAP_MESSAGE_EXCHANGE. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_soap_message_exchange">SOAP message exchange failed</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_START_REDIRECT_LISTENER. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_start_redirect_listener">Redirect listener failed to start</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_timed_out_redirect_listener">Timed out waiting for redirect</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_OSU_ACTIVITY_FOUND. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_no_osu_activity_found">No OSU activity found</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_unexpected_soap_message_status">Unexpected SOAP message status</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_PPS_MO. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_no_pps_mo">Failed to find PPS-MO</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_no_aaa_server_trust_root_node">Failed to find trust root node for AAA server</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_no_remediation_server_trust_root_node">Failed to find trust root node for remediation server</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_no_policy_server_trust_root_node">Failed to find trust root node for policy server</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_retrieve_trust_root_certificates">Failed to retrieve trust root certificates</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_no_aaa_trust_root_certificate">Failed to find trust root certificate for AAA server</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_add_passpoint_configuration">Failed to add PassPoint configuration</string>
-    <!-- Status message of OSU Provider on receiving OSU_FAILURE_OSU_PROVIDER_NOT_FOUND. [CHAR LIMIT=NONE] -->
-    <string name="osu_failure_osu_provider_not_found">Failed to find an OSU provider</string>
-
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_AP_CONNECTING. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_ap_connecting">Connecting</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_AP_CONNECTED. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_ap_connected">Connected</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_SERVER_CONNECTING. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_server_connecting">Connecting to OSU server</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_SERVER_VALIDATED. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_server_validated">OSU server validated</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_SERVER_CONNECTED. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_server_connected">Connected to OSU server</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_INIT_SOAP_EXCHANGE. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_init_soap_exchange">Initial SOAP exchange</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_waiting_for_redirect_response">Waiting for redirect response</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_REDIRECT_RESPONSE_RECEIVED. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_redirect_response_received">Received redirect response</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_SECOND_SOAP_EXCHANGE. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_second_soap_exchange">Second SOAP exchange</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_THIRD_SOAP_EXCHANGE. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_third_soap_exchange">Third SOAP exchange</string>
-    <!-- Status message of OSU Provider on receiving OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS. [CHAR LIMIT=NONE] -->
-    <string name="osu_status_retrieving_trust_root_certs">Retrieving trust root certificates</string>
-
+    <!-- Status message of OSU Provider upon initiating provisioning flow [CHAR LIMIT=NONE] -->
+    <string name="osu_opening_provider">Opening <xliff:g id="passpointProvider" example="Passpoint Provider">%1$s</xliff:g></string>
+    <!-- Status message of OSU Provider when connection fails [CHAR LIMIT=NONE] -->
+    <string name="osu_connect_failed">Couldn\u2019t connect</string>
+    <!-- Status message of OSU Provider after user completes provisioning flow [CHAR LIMIT=NONE] -->
+    <string name="osu_completing_sign_up">Completing sign-up\u2026</string>
+    <!-- Status message of OSU Provider when sign up could not be completed [CHAR LIMIT=NONE] -->
+    <string name="osu_sign_up_failed">Couldn\u2019t complete sign-up. Tap to try again.</string>
     <!-- Status message of OSU Provider on completing provisioning. [CHAR LIMIT=NONE] -->
-    <string name="osu_provisioning_complete">Provisioning complete</string>
+    <string name="osu_sign_up_complete">Sign-up complete. Connecting\u2026</string>
 
     <!-- Speed label for very slow network speed -->
     <string name="speed_label_very_slow">Very Slow</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index c74d9ff..ed8b487 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -888,13 +888,13 @@
 
         if (isOsuProvider()) {
             if (mOsuProvisioningComplete) {
-                summary.append(mContext.getString(R.string.osu_provisioning_complete));
+                summary.append(mContext.getString(R.string.osu_sign_up_complete));
             } else if (mOsuFailure != null) {
                 summary.append(mOsuFailure);
             } else if (mOsuStatus != null) {
                 summary.append(mOsuStatus);
             } else {
-                summary.append(mContext.getString(R.string.tap_to_set_up));
+                summary.append(mContext.getString(R.string.tap_to_sign_up));
             }
         } else if (isActive()) {
             if (isPasspoint()) {
@@ -1554,91 +1554,12 @@
      * All methods are invoked on the Main Thread
      */
     private class AccessPointProvisioningCallback extends ProvisioningCallback {
-        // TODO: Remove logs and implement summary changing logic for these provisioning callbacks.
         @Override
         @MainThread public void onProvisioningFailure(int status) {
-            switch (status) {
-                case OSU_FAILURE_AP_CONNECTION:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_ap_connection);
-                    break;
-                case OSU_FAILURE_SERVER_URL_INVALID:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_server_url_invalid);
-                    break;
-                case OSU_FAILURE_SERVER_CONNECTION:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_server_connection);
-                    break;
-                case OSU_FAILURE_SERVER_VALIDATION:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_server_validation);
-                    break;
-                case OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_service_provider_verification);
-                    break;
-                case OSU_FAILURE_PROVISIONING_ABORTED:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_provisioning_aborted);
-                    break;
-                case OSU_FAILURE_PROVISIONING_NOT_AVAILABLE:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_provisioning_not_available);
-                    break;
-                case OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_invalid_server_url);
-                    break;
-                case OSU_FAILURE_UNEXPECTED_COMMAND_TYPE:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_unexpected_command_type);
-                    break;
-                case OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_unexpected_soap_message_type);
-                    break;
-                case OSU_FAILURE_SOAP_MESSAGE_EXCHANGE:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_soap_message_exchange);
-                    break;
-                case OSU_FAILURE_START_REDIRECT_LISTENER:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_start_redirect_listener);
-                    break;
-                case OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_timed_out_redirect_listener);
-                    break;
-                case OSU_FAILURE_NO_OSU_ACTIVITY_FOUND:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_no_osu_activity_found);
-                    break;
-                case OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_unexpected_soap_message_status);
-                    break;
-                case OSU_FAILURE_NO_PPS_MO:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_no_pps_mo);
-                    break;
-                case OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_no_aaa_server_trust_root_node);
-                    break;
-                case OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_no_remediation_server_trust_root_node);
-                    break;
-                case OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_no_policy_server_trust_root_node);
-                    break;
-                case OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_retrieve_trust_root_certificates);
-                    break;
-                case OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_no_aaa_trust_root_certificate);
-                    break;
-                case OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION:
-                    mOsuFailure = mContext.getString(
-                            R.string.osu_failure_add_passpoint_configuration);
-                    break;
-                case OSU_FAILURE_OSU_PROVIDER_NOT_FOUND:
-                    mOsuFailure = mContext.getString(R.string.osu_failure_osu_provider_not_found);
-                    break;
+            if (TextUtils.equals(mOsuStatus, mContext.getString(R.string.osu_completing_sign_up))) {
+                mOsuFailure = mContext.getString(R.string.osu_sign_up_failed);
+            } else {
+                mOsuFailure = mContext.getString(R.string.osu_connect_failed);
             }
             mOsuStatus = null;
             mOsuProvisioningComplete = false;
@@ -1651,50 +1572,37 @@
 
         @Override
         @MainThread public void onProvisioningStatus(int status) {
+            String newStatus = null;
             switch (status) {
                 case OSU_STATUS_AP_CONNECTING:
-                    mOsuStatus = mContext.getString(R.string.osu_status_ap_connecting);
-                    break;
                 case OSU_STATUS_AP_CONNECTED:
-                    mOsuStatus = mContext.getString(R.string.osu_status_ap_connected);
-                    break;
                 case OSU_STATUS_SERVER_CONNECTING:
-                    mOsuStatus = mContext.getString(R.string.osu_status_server_connecting);
-                    break;
                 case OSU_STATUS_SERVER_VALIDATED:
-                    mOsuStatus = mContext.getString(R.string.osu_status_server_validated);
-                    break;
                 case OSU_STATUS_SERVER_CONNECTED:
-                    mOsuStatus = mContext.getString(R.string.osu_status_server_connected);
-                    break;
                 case OSU_STATUS_INIT_SOAP_EXCHANGE:
-                    mOsuStatus = mContext.getString(R.string.osu_status_init_soap_exchange);
-                    break;
                 case OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE:
-                    mOsuStatus = mContext.getString(
-                            R.string.osu_status_waiting_for_redirect_response);
+                    newStatus = String.format(mContext.getString(R.string.osu_opening_provider),
+                            mOsuProvider.getFriendlyName());
                     break;
                 case OSU_STATUS_REDIRECT_RESPONSE_RECEIVED:
-                    mOsuStatus = mContext.getString(R.string.osu_status_redirect_response_received);
-                    break;
                 case OSU_STATUS_SECOND_SOAP_EXCHANGE:
-                    mOsuStatus = mContext.getString(R.string.osu_status_second_soap_exchange);
-                    break;
                 case OSU_STATUS_THIRD_SOAP_EXCHANGE:
-                    mOsuStatus = mContext.getString(R.string.osu_status_third_soap_exchange);
-                    break;
                 case OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS:
-                    mOsuStatus = mContext.getString(
-                            R.string.osu_status_retrieving_trust_root_certs);
+                    newStatus = mContext.getString(
+                            R.string.osu_completing_sign_up);
                     break;
             }
+            boolean updated = !TextUtils.equals(mOsuStatus, newStatus);
+            mOsuStatus = newStatus;
             mOsuFailure = null;
             mOsuProvisioningComplete = false;
-            ThreadUtils.postOnMainThread(() -> {
-                if (mAccessPointListener != null) {
-                    mAccessPointListener.onAccessPointChanged(AccessPoint.this);
-                }
-            });
+            if (updated) {
+                ThreadUtils.postOnMainThread(() -> {
+                    if (mAccessPointListener != null) {
+                        mAccessPointListener.onAccessPointChanged(AccessPoint.this);
+                    }
+                });
+            }
         }
 
         @Override
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 4453121..23e5f0e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -4231,7 +4231,7 @@
 
                         String defLocationMode = Integer.toString(
                                 !TextUtils.isEmpty(locationProvidersAllowed.getValue())
-                                        ? Secure.LOCATION_MODE_HIGH_ACCURACY
+                                        ? Secure.LOCATION_MODE_ON
                                         : Secure.LOCATION_MODE_OFF);
                         secureSettings.insertSettingLocked(
                                 Secure.LOCATION_MODE, defLocationMode,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index c3c3f25..c032683 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -145,6 +145,7 @@
     <uses-permission android:name="android.permission.SET_TIME_ZONE" />
     <uses-permission android:name="android.permission.DISABLE_HIDDEN_API_CHECKS" />
     <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
+    <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
     <!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) -->
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
     <!-- Permission needed to hold a wakelock in dumpstate.cpp (drop_root_user()) -->
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3453e79..815ae9a 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -22,6 +22,11 @@
         android:sharedUserId="android.uid.systemui"
         coreApp="true">
 
+    <!-- Using OpenGL ES 2.0 -->
+    <uses-feature
+        android:glEsVersion="0x00020000"
+        android:required="true" />
+
     <!-- SysUI must be the one to define this permission; its name is
          referenced by the core OS. -->
     <permission android:name="android.permission.systemui.IDENTITY"
@@ -593,11 +598,6 @@
                 android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
                 android:process=":ui"
                 android:visibleToInstantApps="true">
-            <intent-filter>
-                <action android:name="android.intent.action.CHOOSER_UI" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
-            </intent-filter>
         </activity>
 
         <!-- Doze with notifications, run in main sysui process for every user  -->
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 2f6e32b..e7e2c1a 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -1,6 +1,6 @@
 set noparent
 
-dsandler@google.com
+dsandler@android.com
 
 adamcohen@google.com
 asc@google.com
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 7432f9c..41acf82 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -405,7 +405,7 @@
     <!-- Header for typographic clock face. [CHAR LIMIT=8] -->
     <string name="type_clock_header">It\u2019s</string>
 
-    <!-- Hour displayed in words on the typographic clock face. [CHAR LIMIT=8] -->
+    <!-- Hour displayed in words on the typographic clock face. [CHAR LIMIT=12] -->
     <string-array name="type_clock_hours">
         <item>Twelve</item>
         <item>One</item>
@@ -421,7 +421,7 @@
         <item>Eleven</item>
     </string-array>
 
-    <!-- Minutes displayed in words on the typographic clock face. [CHAR LIMIT=16] -->
+    <!-- Minutes displayed in words on the typographic clock face. [CHAR LIMIT=20] -->
     <string-array name="type_clock_minutes">
         <item>O\u2019Clock</item>
         <item>O\u2019One</item>
diff --git a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
new file mode 100644
index 0000000..11d73a9
--- /dev/null
+++ b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
@@ -0,0 +1,33 @@
+precision mediump float;
+
+uniform sampler2D uTexture;
+uniform float uCenterReveal;
+uniform float uReveal;
+uniform float uAod2Opacity;
+uniform int uAodMode;
+varying vec2 vTextureCoordinates;
+
+vec3 luminosity(vec3 color) {
+    float lum = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
+    return vec3(lum);
+}
+
+vec4 transform(vec3 diffuse) {
+    // TODO: Add well comments here, tracking on b/123615467.
+    vec3 lum = luminosity(diffuse);
+    diffuse = mix(diffuse, lum, smoothstep(0., uCenterReveal, uReveal));
+    float val = mix(uReveal, uCenterReveal, step(uCenterReveal, uReveal));
+    diffuse = smoothstep(val, 1.0, diffuse);
+    diffuse *= uAod2Opacity * (1. - smoothstep(uCenterReveal, 1., uReveal));
+    return vec4(diffuse.r, diffuse.g, diffuse.b, 1.);
+}
+
+void main() {
+    vec4 fragColor = texture2D(uTexture, vTextureCoordinates);
+    // TODO: Remove the branch logic here, tracking on b/123615467.
+    if (uAodMode != 0) {
+        gl_FragColor = transform(fragColor.rgb);
+    } else {
+        gl_FragColor = fragColor;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl
new file mode 100644
index 0000000..4393e2b
--- /dev/null
+++ b/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl
@@ -0,0 +1,8 @@
+attribute vec4 aPosition;
+attribute vec2 aTextureCoordinates;
+varying vec2 vTextureCoordinates;
+
+void main() {
+    vTextureCoordinates = aTextureCoordinates;
+    gl_Position = aPosition;
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 2aecc24..5040942 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -19,8 +19,11 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.app.WallpaperManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.RecordingCanvas;
@@ -28,7 +31,9 @@
 import android.graphics.RectF;
 import android.graphics.Region.Op;
 import android.hardware.display.DisplayManager;
+import android.opengl.GLSurfaceView;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Trace;
 import android.service.wallpaper.WallpaperService;
@@ -39,6 +44,7 @@
 import android.view.SurfaceHolder;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -51,12 +57,17 @@
 public class ImageWallpaper extends WallpaperService {
     private static final String TAG = "ImageWallpaper";
     private static final String GL_LOG_TAG = "ImageWallpaperGL";
+    // TODO: Testing purpose, need to remove later, b/123616712.
+    private static final String SENSOR_EVENT_AWAKE = "systemui.test.event.awake";
+    // TODO: Testing purpose, need to remove later, b/123616712.
+    private static final String SENSOR_EVENT_SLEEP = "systemui.test.event.sleep";
     private static final boolean DEBUG = false;
     private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu";
     private static final long DELAY_FORGET_WALLPAPER = 5000;
 
     private WallpaperManager mWallpaperManager;
     private DrawableEngine mEngine;
+    private GLEngine mGlEngine;
 
     @Override
     public void onCreate() {
@@ -73,10 +84,112 @@
 
     @Override
     public Engine onCreateEngine() {
-        mEngine = new DrawableEngine();
-        return mEngine;
+        mGlEngine = new GLEngine(this);
+        return mGlEngine;
     }
 
+    class GLEngine extends Engine {
+        private GLWallpaperSurfaceView mWallpaperSurfaceView;
+
+        GLEngine(Context context) {
+            mWallpaperSurfaceView = new GLWallpaperSurfaceView(context);
+            mWallpaperSurfaceView.setRenderer(
+                    new ImageWallpaperRenderer(context, mWallpaperSurfaceView));
+            mWallpaperSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+            setOffsetNotificationsEnabled(true);
+        }
+
+        @Override
+        public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
+            if (mWallpaperSurfaceView != null) {
+                mWallpaperSurfaceView.notifyAmbientModeChanged(inAmbientMode);
+            }
+        }
+
+        @Override
+        public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
+                float yOffsetStep, int xPixelOffset, int yPixelOffset) {
+            if (mWallpaperSurfaceView != null) {
+                mWallpaperSurfaceView.notifyOffsetsChanged(xOffset, yOffset);
+            }
+        }
+
+        private class GLWallpaperSurfaceView extends GLSurfaceView implements ImageGLView {
+            private SensorEventListener mEventListener;
+            private WallpaperStatusListener mWallpaperChangedListener;
+
+            // TODO: Testing purpose, need to remove later, b/123616712.
+            /**
+             * For testing only: adb shell am broadcast -a <INTENT>
+             */
+            private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (intent == null) {
+                        return;
+                    }
+                    switch (intent.getAction()) {
+                        case SENSOR_EVENT_AWAKE:
+                            notifySensorEvents(true);
+                            break;
+                        case SENSOR_EVENT_SLEEP:
+                            notifySensorEvents(false);
+                            break;
+                    }
+                }
+            };
+
+            GLWallpaperSurfaceView(Context context) {
+                super(context);
+                setEGLContextClientVersion(2);
+                // TODO: Testing purpose, need to remove later, b/123616712.
+                if (Build.IS_DEBUGGABLE) {
+                    IntentFilter filter = new IntentFilter();
+                    filter.addAction(SENSOR_EVENT_AWAKE);
+                    filter.addAction(SENSOR_EVENT_SLEEP);
+                    registerReceiver(mReceiver, filter);
+                }
+            }
+
+            @Override
+            public SurfaceHolder getHolder() {
+                return getSurfaceHolder();
+            }
+
+            @Override
+            public void setRenderer(Renderer renderer) {
+                super.setRenderer(renderer);
+                mEventListener = (SensorEventListener) renderer;
+                mWallpaperChangedListener = (WallpaperStatusListener) renderer;
+            }
+
+            private void notifySensorEvents(boolean reach) {
+                if (mEventListener != null) {
+                    mEventListener.onSensorEvent(reach);
+                }
+            }
+
+            private void notifyAmbientModeChanged(boolean inAmbient) {
+                if (mWallpaperChangedListener != null) {
+                    mWallpaperChangedListener.onAmbientModeChanged(inAmbient);
+                }
+            }
+
+            private void notifyOffsetsChanged(float xOffset, float yOffset) {
+                if (mWallpaperChangedListener != null) {
+                    mWallpaperChangedListener.onOffsetsChanged(
+                            xOffset, yOffset, getHolder().getSurfaceFrame());
+                }
+            }
+
+            @Override
+            public void render() {
+                requestRender();
+            }
+        }
+    }
+
+    // TODO: Remove this engine, tracking on b/123617158.
     class DrawableEngine extends Engine {
         private final Runnable mUnloadWallpaperCallback = () -> {
             unloadWallpaper(false /* forgetSize */);
@@ -564,4 +677,46 @@
             }
         }
     }
+
+    /**
+     * A listener to trace sensor event.
+     */
+    public interface SensorEventListener {
+
+        /**
+         * Called back while sensor event comes.
+         * @param reach The status of sensor.
+         */
+        void onSensorEvent(boolean reach);
+    }
+
+    /**
+     * A listener to trace status of image wallpaper.
+     */
+    public interface WallpaperStatusListener {
+
+        /**
+         * Called back while ambient mode changes.
+         * @param inAmbientMode true if is in ambient mode, false otherwise.
+         */
+        void onAmbientModeChanged(boolean inAmbientMode);
+
+        /**
+         * Called back while wallpaper offsets.
+         * @param xOffset The offset portion along x.
+         * @param yOffset The offset portion along y.
+         */
+        void onOffsetsChanged(float xOffset, float yOffset, Rect frame);
+    }
+
+    /**
+     * An abstraction for view of GLRenderer.
+     */
+    public interface ImageGLView {
+
+        /**
+         * Ask the view to render.
+         */
+        void render();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index f66a57b..9b3d7ed 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -137,8 +137,10 @@
     }
 
     public NotificationIconAreaController createNotificationIconAreaController(Context context,
-            StatusBar statusBar, StatusBarStateController statusBarStateController) {
-        return new NotificationIconAreaController(context, statusBar, statusBarStateController);
+            StatusBar statusBar, StatusBarStateController statusBarStateController,
+            NotificationListener listener) {
+        return new NotificationIconAreaController(context, statusBar, statusBarStateController,
+                listener);
     }
 
     public KeyguardIndicationController createKeyguardIndicationController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedViewContainer.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedViewContainer.java
index 71ae1f8..231e725 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedViewContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedViewContainer.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.drawable.ShapeDrawable;
 import android.text.TextUtils;
@@ -68,9 +69,15 @@
         mPointerView = findViewById(R.id.pointer_view);
         int width = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
         int height = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
+
+        TypedArray ta = getContext().obtainStyledAttributes(
+                new int[] {android.R.attr.colorBackgroundFloating});
+        int bgColor = ta.getColor(0, Color.WHITE);
+        ta.recycle();
+
         ShapeDrawable triangleDrawable = new ShapeDrawable(
                 TriangleShape.create(width, height, true /* pointUp */));
-        triangleDrawable.setTint(Color.WHITE); // TODO: dark mode
+        triangleDrawable.setTint(bgColor);
         mPointerView.setBackground(triangleDrawable);
         mHeaderView = findViewById(R.id.bubble_content_header);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 83fd970..cbca2fc 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -237,15 +237,19 @@
      * Sets the bubble that should be expanded and expands if needed.
      */
     public void setExpandedBubble(BubbleView bubbleToExpand) {
+        if (mIsExpanded && !bubbleToExpand.equals(mExpandedBubble)) {
+            // Previously expanded, notify that this bubble is no longer expanded
+            notifyExpansionChanged(mExpandedBubble, false /* expanded */);
+        }
         mExpandedBubble = bubbleToExpand;
-        boolean prevExpanded = mIsExpanded;
-        mIsExpanded = true;
-        if (!prevExpanded) {
+        if (!mIsExpanded) {
             // If we weren't previously expanded we should animate open.
             animateExpansion(true /* expand */);
         } else {
-            // If we were expanded just update the views
+            // Otherwise just update the views
+            // TODO: probably animate / page to expanded one
             updateExpandedBubble();
+            updatePointerPosition();
             requestUpdate();
         }
         mExpandedBubble.getEntry().setShowInShadeWhenBubble(false);
@@ -291,12 +295,12 @@
             int nextIndex = bubbleCount > removedIndex ? removedIndex : bubbleCount - 1;
             BubbleView expandedBubble = (BubbleView) mBubbleContainer.getChildAt(nextIndex);
             setExpandedBubble(expandedBubble);
+            requestUpdate();
         }
         mIsExpanded = wasExpanded && mBubbleContainer.getChildCount() > 0;
         if (wasExpanded != mIsExpanded) {
             notifyExpansionChanged(mExpandedBubble, mIsExpanded);
         }
-        requestUpdate();
     }
 
     /**
@@ -373,9 +377,7 @@
     public void expandStack() {
         if (!mIsExpanded) {
             mExpandedBubble = getTopBubble();
-            mExpandedBubble.getEntry().setShowInShadeWhenBubble(false);
-            animateExpansion(true /* shouldExpand */);
-            notifyExpansionChanged(mExpandedBubble, true /* expanded */);
+            setExpandedBubble(mExpandedBubble);
         }
     }
 
@@ -387,7 +389,6 @@
             mIsExpanded = shouldExpand;
             updateExpandedBubble();
             applyCurrentState();
-            //requestUpdate();
 
             mIsAnimating = true;
 
@@ -400,7 +401,10 @@
             if (shouldExpand) {
                 mBubbleContainer.setController(mExpandedAnimationController);
                 mExpandedAnimationController.expandFromStack(
-                                mStackAnimationController.getStackPosition(), updateAfter);
+                                mStackAnimationController.getStackPosition(), () -> {
+                                updatePointerPosition();
+                                updateAfter.run();
+                        });
             } else {
                 mBubbleContainer.cancelAllAnimations();
                 mExpandedAnimationController.collapseBackToStack(
@@ -649,10 +653,7 @@
             }
             // Bubble with notification as expanded state doesn't need a header / title
             mExpandedViewContainer.setHeaderText(null);
-
         }
-        float pointerPosition = mExpandedBubble.getPosition().x + (mExpandedBubble.getWidth() / 2);
-        mExpandedViewContainer.setPointerPosition((int) pointerPosition);
     }
 
     private void applyCurrentState() {
@@ -690,6 +691,14 @@
         }
     }
 
+    private void updatePointerPosition() {
+        if (mExpandedBubble != null) {
+            float pointerPosition = mExpandedBubble.getPosition().x
+                    + (mExpandedBubble.getWidth() / 2f);
+            mExpandedViewContainer.setPointerPosition((int) pointerPosition);
+        }
+    }
+
     private void applyRowState(ExpandableNotificationRow view) {
         view.reset();
         view.setHeadsUp(false);
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java
new file mode 100644
index 0000000..d03b00b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 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.glwallpaper;
+
+import static android.opengl.GLES20.GL_FRAGMENT_SHADER;
+import static android.opengl.GLES20.GL_VERTEX_SHADER;
+import static android.opengl.GLES20.glAttachShader;
+import static android.opengl.GLES20.glCompileShader;
+import static android.opengl.GLES20.glCreateProgram;
+import static android.opengl.GLES20.glCreateShader;
+import static android.opengl.GLES20.glGetAttribLocation;
+import static android.opengl.GLES20.glGetUniformLocation;
+import static android.opengl.GLES20.glLinkProgram;
+import static android.opengl.GLES20.glShaderSource;
+import static android.opengl.GLES20.glUseProgram;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * This class takes charge of linking shader codes and then return a handle for OpenGL ES program.
+ */
+class ImageGLProgram {
+    private static final String TAG = ImageGLProgram.class.getSimpleName();
+
+    private Context mContext;
+    private int mProgramHandle;
+
+    ImageGLProgram(Context context) {
+        mContext = context.getApplicationContext();
+    }
+
+    private int loadShaderProgram(int vertexId, int fragmentId) {
+        final String vertexSrc = getShaderResource(vertexId);
+        final String fragmentSrc = getShaderResource(fragmentId);
+        final int vertexHandle = getShaderHandle(GL_VERTEX_SHADER, vertexSrc);
+        final int fragmentHandle = getShaderHandle(GL_FRAGMENT_SHADER, fragmentSrc);
+        return getProgramHandle(vertexHandle, fragmentHandle);
+    }
+
+    private String getShaderResource(int shaderId) {
+        Resources res = mContext.getResources();
+        StringBuilder code = new StringBuilder();
+
+        try (BufferedReader reader = new BufferedReader(
+                new InputStreamReader(res.openRawResource(shaderId)))) {
+            String nextLine;
+            while ((nextLine = reader.readLine()) != null) {
+                code.append(nextLine).append("\n");
+            }
+        } catch (IOException | Resources.NotFoundException ex) {
+            Log.d(TAG, "Can not read the shader source", ex);
+            code = null;
+        }
+
+        return code == null ? "" : code.toString();
+    }
+
+    private int getShaderHandle(int type, String src) {
+        final int shader = glCreateShader(type);
+        if (shader == 0) {
+            Log.d(TAG, "Create shader failed, type=" + type);
+            return 0;
+        }
+        glShaderSource(shader, src);
+        glCompileShader(shader);
+        return shader;
+    }
+
+    private int getProgramHandle(int vertexHandle, int fragmentHandle) {
+        final int program = glCreateProgram();
+        if (program == 0) {
+            Log.d(TAG, "Can not create OpenGL ES program");
+            return 0;
+        }
+
+        glAttachShader(program, vertexHandle);
+        glAttachShader(program, fragmentHandle);
+        glLinkProgram(program);
+        return program;
+    }
+
+    boolean useGLProgram(int vertexResId, int fragmentResId) {
+        mProgramHandle = loadShaderProgram(vertexResId, fragmentResId);
+        glUseProgram(mProgramHandle);
+        return true;
+    }
+
+    int getAttributeHandle(String name) {
+        return glGetAttribLocation(mProgramHandle, name);
+    }
+
+    int getUniformHandle(String name) {
+        return glGetUniformLocation(mProgramHandle, name);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
new file mode 100644
index 0000000..4e07872
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2019 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.glwallpaper;
+
+import static android.opengl.GLES20.GL_FLOAT;
+import static android.opengl.GLES20.GL_LINEAR;
+import static android.opengl.GLES20.GL_TEXTURE0;
+import static android.opengl.GLES20.GL_TEXTURE_2D;
+import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
+import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
+import static android.opengl.GLES20.GL_TRIANGLES;
+import static android.opengl.GLES20.glActiveTexture;
+import static android.opengl.GLES20.glBindTexture;
+import static android.opengl.GLES20.glDrawArrays;
+import static android.opengl.GLES20.glEnableVertexAttribArray;
+import static android.opengl.GLES20.glGenTextures;
+import static android.opengl.GLES20.glTexParameteri;
+import static android.opengl.GLES20.glUniform1i;
+import static android.opengl.GLES20.glVertexAttribPointer;
+
+import android.graphics.Bitmap;
+import android.opengl.GLUtils;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+/**
+ * This class takes charge of the geometry data like vertices and texture coordinates.
+ * It delivers these data to opengl runtime and triggers draw calls if necessary.
+ */
+class ImageGLWallpaper {
+    private static final String TAG = ImageGLWallpaper.class.getSimpleName();
+
+    static final String A_POSITION = "aPosition";
+    static final String A_TEXTURE_COORDINATES = "aTextureCoordinates";
+    static final String U_CENTER_REVEAL = "uCenterReveal";
+    static final String U_REVEAL = "uReveal";
+    static final String U_AOD2OPACITY = "uAod2Opacity";
+    static final String U_TEXTURE = "uTexture";
+    static final String U_AOD_MODE = "uAodMode";
+
+    private static final int HANDLE_UNDEFINED = -1;
+    private static final int POSITION_COMPONENT_COUNT = 2;
+    private static final int TEXTURE_COMPONENT_COUNT = 2;
+    private static final int BYTES_PER_FLOAT = 4;
+
+    // Vertices to define the square with 2 triangles.
+    private static final float[] VERTICES = {
+            -1.0f,  -1.0f,
+            +1.0f,  -1.0f,
+            +1.0f,  +1.0f,
+            +1.0f,  +1.0f,
+            -1.0f,  +1.0f,
+            -1.0f,  -1.0f
+    };
+
+    // Texture coordinates that maps to vertices.
+    private static final float[] TEXTURES = {
+            0f, 1f,
+            1f, 1f,
+            1f, 0f,
+            1f, 0f,
+            0f, 0f,
+            0f, 1f
+    };
+
+    private final FloatBuffer mVertexBuffer;
+    private final FloatBuffer mTextureBuffer;
+    private final ImageGLProgram mProgram;
+
+    private int mAttrPosition;
+    private int mAttrTextureCoordinates;
+    private int mUniAod2Opacity;
+    private int mUniAodMode;
+    private int mUniCenterReveal;
+    private int mUniReveal;
+    private int mUniTexture;
+    private int mTextureId;
+
+    ImageGLWallpaper(ImageGLProgram program) {
+        mProgram = program;
+
+        // Create an float array in opengles runtime (native) and put vertex data.
+        mVertexBuffer = ByteBuffer.allocateDirect(VERTICES.length * BYTES_PER_FLOAT)
+            .order(ByteOrder.nativeOrder())
+            .asFloatBuffer();
+        mVertexBuffer.put(VERTICES);
+        mVertexBuffer.position(0);
+
+        // Create an float array in opengles runtime (native) and put texture data.
+        mTextureBuffer = ByteBuffer.allocateDirect(TEXTURES.length * BYTES_PER_FLOAT)
+            .order(ByteOrder.nativeOrder())
+            .asFloatBuffer();
+        mTextureBuffer.put(TEXTURES);
+        mTextureBuffer.position(0);
+    }
+
+    void setup() {
+        setupAttributes();
+        setupUniforms();
+    }
+
+    private void setupAttributes() {
+        mAttrPosition = mProgram.getAttributeHandle(A_POSITION);
+        mVertexBuffer.position(0);
+        glVertexAttribPointer(mAttrPosition, POSITION_COMPONENT_COUNT, GL_FLOAT,
+                false, 0, mVertexBuffer);
+        glEnableVertexAttribArray(mAttrPosition);
+
+        mAttrTextureCoordinates = mProgram.getAttributeHandle(A_TEXTURE_COORDINATES);
+        mTextureBuffer.position(0);
+        glVertexAttribPointer(mAttrTextureCoordinates, TEXTURE_COMPONENT_COUNT, GL_FLOAT,
+                false, 0, mTextureBuffer);
+        glEnableVertexAttribArray(mAttrTextureCoordinates);
+    }
+
+    private void setupUniforms() {
+        mUniAod2Opacity = mProgram.getUniformHandle(U_AOD2OPACITY);
+        mUniAodMode = mProgram.getUniformHandle(U_AOD_MODE);
+        mUniCenterReveal = mProgram.getUniformHandle(U_CENTER_REVEAL);
+        mUniReveal = mProgram.getUniformHandle(U_REVEAL);
+        mUniTexture = mProgram.getUniformHandle(U_TEXTURE);
+    }
+
+    int getHandle(String name) {
+        switch (name) {
+            case A_POSITION:
+                return mAttrPosition;
+            case A_TEXTURE_COORDINATES:
+                return mAttrTextureCoordinates;
+            case U_AOD2OPACITY:
+                return mUniAod2Opacity;
+            case U_AOD_MODE:
+                return mUniAodMode;
+            case U_CENTER_REVEAL:
+                return mUniCenterReveal;
+            case U_REVEAL:
+                return mUniReveal;
+            case U_TEXTURE:
+                return mUniTexture;
+            default:
+                return HANDLE_UNDEFINED;
+        }
+    }
+
+    void draw() {
+        glDrawArrays(GL_TRIANGLES, 0, VERTICES.length / 2);
+    }
+
+    void setupTexture(Bitmap bitmap) {
+        final int[] tids = new int[1];
+
+        if (bitmap == null) {
+            Log.w(TAG, "setupTexture: invalid bitmap");
+            return;
+        }
+
+        // Generate one texture object and store the id in tids[0].
+        glGenTextures(1, tids, 0);
+        if (tids[0] == 0) {
+            Log.w(TAG, "setupTexture: glGenTextures() failed");
+            return;
+        }
+
+        // Bind a named texture to a texturing target.
+        glBindTexture(GL_TEXTURE_2D, tids[0]);
+        // Load the bitmap data and copy it over into the texture object that is currently bound.
+        GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
+        // Use bilinear texture filtering when minification.
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        // Use bilinear texture filtering when magnification.
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+        mTextureId = tids[0];
+    }
+
+    void useTexture() {
+        // Set the active texture unit to texture unit 0.
+        glActiveTexture(GL_TEXTURE0);
+        // Bind the texture to this unit.
+        glBindTexture(GL_TEXTURE_2D, mTextureId);
+        // Let the texture sampler in fragment shader to read form this texture unit.
+        glUniform1i(mUniTexture, 0);
+    }
+
+    void adjustTextureCoordinates(Bitmap bitmap, int surfaceWidth, int surfaceHeight,
+            float xOffset, float yOffset) {
+        if (bitmap == null) {
+            Log.d(TAG, "adjustTextureCoordinates: invalid bitmap");
+            return;
+        }
+
+        float ratioW = 1f;
+        float ratioH = 1f;
+        int bitmapWidth = bitmap.getWidth();
+        int bitmapHeight = bitmap.getHeight();
+
+        boolean adjustWidth = bitmapWidth > surfaceWidth;
+        if (adjustWidth) {
+            ratioW = (float) surfaceWidth / bitmapWidth;
+            float referenceX = xOffset + ratioW > 1f ? 1f - ratioW : xOffset;
+            for (int i = 0; i < TEXTURES.length; i += 2) {
+                if (i == 2 || i == 4 || i == 6) {
+                    TEXTURES[i] = Math.min(1f, referenceX + ratioW);
+                } else {
+                    TEXTURES[i] = referenceX;
+                }
+            }
+        }
+
+        boolean adjustHeight = bitmapHeight > surfaceHeight;
+        if (adjustHeight) {
+            ratioH = (float) surfaceHeight / bitmapHeight;
+            float referenceY = yOffset + ratioH > 1f ? 1f - ratioH : yOffset;
+            for (int i = 1; i < TEXTURES.length; i += 2) {
+                if (i == 1 || i == 3 || i == 11) {
+                    TEXTURES[i] = Math.min(1f, referenceY + ratioH);
+                } else {
+                    TEXTURES[i] = referenceY;
+                }
+            }
+        }
+
+        if (adjustWidth || adjustHeight) {
+            mTextureBuffer.put(TEXTURES);
+            mTextureBuffer.position(0);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
new file mode 100644
index 0000000..477e7d7e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2019 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.glwallpaper;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * A helper class that computes histogram and percentile 85 from a bitmap.
+ * Percentile 85 will be computed each time the user picks a new image wallpaper.
+ */
+class ImageProcessHelper {
+    private static final String TAG = ImageProcessHelper.class.getSimpleName();
+    private static final float DEFAULT_PER85 = 0.8f;
+    private static final int MSG_UPDATE_PER85 = 1;
+
+    /**
+     * This color matrix will be applied to each pixel to get luminance from rgb by below formula:
+     * Luminance = .2126f * r + .7152f * g + .0722f * b.
+     */
+    private static final float[] LUMINOSITY_MATRIX = new float[] {
+            .2126f,     .0000f,     .0000f,     .0000f,     .0000f,
+            .0000f,     .7152f,     .0000f,     .0000f,     .0000f,
+            .0000f,     .0000f,     .0722f,     .0000f,     .0000f,
+            .0000f,     .0000f,     .0000f,     1.000f,     .0000f
+    };
+
+    private final Handler mHandler = new Handler(new Callback() {
+        @Override
+        public boolean handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_UPDATE_PER85:
+                    mPer85 = (float) msg.obj;
+                    return true;
+                default:
+                    return false;
+            }
+        }
+    });
+
+    private float mPer85 = DEFAULT_PER85;
+
+    void startComputingPercentile85(Bitmap bitmap) {
+        new Per85ComputeTask(mHandler).execute(bitmap);
+    }
+
+    float getPercentile85() {
+        return mPer85;
+    }
+
+    private static class Per85ComputeTask extends AsyncTask<Bitmap, Void, Float> {
+        private Handler mUpdateHandler;
+
+        Per85ComputeTask(Handler handler) {
+            super(handler);
+            mUpdateHandler = handler;
+        }
+
+        @Override
+        protected Float doInBackground(Bitmap... bitmaps) {
+            Bitmap bitmap = bitmaps[0];
+            if (bitmap != null) {
+                int[] histogram = processHistogram(bitmap);
+                return computePercentile85(bitmap, histogram);
+            }
+            Log.e(TAG, "Per85ComputeTask: Can't get bitmap");
+            return DEFAULT_PER85;
+        }
+
+        @Override
+        protected void onPostExecute(Float result) {
+            Message msg = mUpdateHandler.obtainMessage(MSG_UPDATE_PER85, result);
+            mUpdateHandler.sendMessage(msg);
+        }
+
+        private int[] processHistogram(Bitmap bitmap) {
+            int width = bitmap.getWidth();
+            int height = bitmap.getHeight();
+
+            Bitmap target = Bitmap.createBitmap(width, height, bitmap.getConfig());
+            Canvas canvas = new Canvas(target);
+            ColorMatrix cm = new ColorMatrix(LUMINOSITY_MATRIX);
+            Paint paint = new Paint();
+            paint.setColorFilter(new ColorMatrixColorFilter(cm));
+            canvas.drawBitmap(bitmap, new Matrix(), paint);
+
+            // TODO: Fine tune the performance here, tracking on b/123615079.
+            int[] histogram = new int[256];
+            for (int row = 0; row < height; row++) {
+                for (int col = 0; col < width; col++) {
+                    int pixel = target.getPixel(col, row);
+                    int y = Color.red(pixel) + Color.green(pixel) + Color.blue(pixel);
+                    histogram[y]++;
+                }
+            }
+
+            return histogram;
+        }
+
+        private float computePercentile85(Bitmap bitmap, int[] histogram) {
+            float per85 = DEFAULT_PER85;
+            int pixelCount = bitmap.getWidth() * bitmap.getHeight();
+            float[] acc = new float[256];
+            for (int i = 0; i < acc.length; i++) {
+                acc[i] = (float) histogram[i] / pixelCount;
+                float prev = i == 0 ? 0f : acc[i - 1];
+                float next = acc[i];
+                float idx = (float) (i + 1) / 255;
+                float sum = prev + next;
+                if (prev < 0.85f && sum >= 0.85f) {
+                    per85 = idx;
+                }
+                if (i > 0) {
+                    acc[i] += acc[i - 1];
+                }
+            }
+            return per85;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
new file mode 100644
index 0000000..787972c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 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.glwallpaper;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+
+import com.android.systemui.Interpolators;
+
+/**
+ * Use ValueAnimator and appropriate interpolator to control the progress of reveal transition.
+ * The transition will happen while getting awake and quit events.
+ */
+class ImageRevealHelper {
+    private static final String TAG = ImageRevealHelper.class.getSimpleName();
+    private static final float MAX_REVEAL = 0f;
+    private static final float MIN_REVEAL = 1f;
+    private static final int REVEAL_DURATION = 1000;
+
+    private final ValueAnimator mAnimator;
+    private final RevealStateListener mRevealListener;
+    private float mReveal = MIN_REVEAL;
+    private boolean mAwake = false;
+
+    ImageRevealHelper(RevealStateListener listener) {
+        mRevealListener = listener;
+        mAnimator = ValueAnimator.ofFloat();
+        mAnimator.setDuration(REVEAL_DURATION);
+        mAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        mAnimator.addUpdateListener(animator -> {
+            mReveal = (float) animator.getAnimatedValue();
+            if (mRevealListener != null) {
+                mRevealListener.onRevealStateChanged();
+            }
+        });
+        mAnimator.addListener(new AnimatorListenerAdapter() {
+            private boolean mIsCanceled;
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mIsCanceled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (!mIsCanceled) {
+                    mAwake = !mAwake;
+                }
+                mIsCanceled = false;
+            }
+        });
+    }
+
+    private void animate() {
+        mAnimator.cancel();
+        mAnimator.setFloatValues(mReveal, !mAwake ? MIN_REVEAL : MAX_REVEAL);
+        mAnimator.start();
+    }
+
+    public float getReveal() {
+        return mReveal;
+    }
+
+    public boolean isAwake() {
+        return mAwake;
+    }
+
+    void updateAwake(boolean awake) {
+        mAwake = awake;
+        animate();
+    }
+
+    void sleep() {
+        mReveal = MIN_REVEAL;
+        mAwake = false;
+    }
+
+    /**
+     * A listener to trace value changes of reveal.
+     */
+    public interface RevealStateListener {
+
+        /**
+         * Called back while reveal status changes.
+         */
+        void onRevealStateChanged();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
new file mode 100644
index 0000000..8916b28
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2019 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.glwallpaper;
+
+import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
+import static android.opengl.GLES20.glClear;
+import static android.opengl.GLES20.glClearColor;
+import static android.opengl.GLES20.glUniform1f;
+import static android.opengl.GLES20.glUniform1i;
+import static android.opengl.GLES20.glViewport;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.opengl.GLSurfaceView;
+import android.util.Log;
+
+import com.android.systemui.ImageWallpaper;
+import com.android.systemui.ImageWallpaper.ImageGLView;
+import com.android.systemui.R;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A GL renderer for image wallpaper.
+ */
+public class ImageWallpaperRenderer implements GLSurfaceView.Renderer,
+        ImageWallpaper.SensorEventListener, ImageWallpaper.WallpaperStatusListener,
+        ImageRevealHelper.RevealStateListener {
+    private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
+
+    private final WallpaperManager mWallpaperManager;
+    private final ImageGLProgram mProgram;
+    private final ImageGLWallpaper mWallpaper;
+    private final ImageProcessHelper mImageProcessHelper;
+    private final ImageRevealHelper mImageRevealHelper;
+    private final ImageGLView mGLView;
+    private boolean mIsInAmbientMode;
+    private float mXOffset = 0f;
+    private float mYOffset = 0f;
+
+    public ImageWallpaperRenderer(Context context, ImageGLView glView) {
+        mWallpaperManager = context.getSystemService(WallpaperManager.class);
+        if (mWallpaperManager == null) {
+            Log.w(TAG, "WallpaperManager not available");
+        }
+
+        mProgram = new ImageGLProgram(context);
+        mWallpaper = new ImageGLWallpaper(mProgram);
+        mImageProcessHelper = new ImageProcessHelper();
+        mImageRevealHelper = new ImageRevealHelper(this);
+        mGLView = glView;
+
+        if (mWallpaperManager != null) {
+            // Compute per85 as transition threshold, this is an async work.
+            mImageProcessHelper.startComputingPercentile85(mWallpaperManager.getBitmap());
+        }
+    }
+
+    @Override
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        glClearColor(0f, 0f, 0f, 1.0f);
+        mProgram.useGLProgram(
+                R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader);
+        mWallpaper.setup();
+        mWallpaper.setupTexture(mWallpaperManager.getBitmap());
+    }
+
+    @Override
+    public void onSurfaceChanged(GL10 gl, int width, int height) {
+        glViewport(0, 0, width, height);
+        mWallpaper.adjustTextureCoordinates(mWallpaperManager.getBitmap(),
+                width, height, mXOffset, mYOffset);
+    }
+
+    @Override
+    public void onDrawFrame(GL10 gl) {
+        float threshold = mImageProcessHelper.getPercentile85();
+        float reveal = mImageRevealHelper.getReveal();
+
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), .25f);
+        glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_CENTER_REVEAL), threshold);
+        glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
+        glUniform1i(mWallpaper.getHandle(ImageGLWallpaper.U_AOD_MODE), mIsInAmbientMode ? 1 : 0);
+
+        mWallpaper.useTexture();
+        mWallpaper.draw();
+    }
+
+    @Override
+    public void onSensorEvent(boolean awake) {
+        mImageRevealHelper.updateAwake(awake);
+    }
+
+    @Override
+    public void onAmbientModeChanged(boolean inAmbientMode) {
+        mIsInAmbientMode = inAmbientMode;
+        if (inAmbientMode) {
+            mImageRevealHelper.sleep();
+        }
+        requestRender();
+    }
+
+    @Override
+    public void onOffsetsChanged(float xOffset, float yOffset, Rect frame) {
+        if (frame == null || mWallpaperManager == null
+                || (xOffset == mXOffset && yOffset == mYOffset)) {
+            return;
+        }
+
+        Bitmap bitmap = mWallpaperManager.getBitmap();
+        if (bitmap == null) {
+            return;
+        }
+
+        int width = frame.width();
+        int height = frame.height();
+        mXOffset = xOffset;
+        mYOffset = yOffset;
+
+        mWallpaper.adjustTextureCoordinates(bitmap, width, height, mXOffset, mYOffset);
+        requestRender();
+    }
+
+    @Override
+    public void onRevealStateChanged() {
+        requestRender();
+    }
+
+    private void requestRender() {
+        if (mGLView != null) {
+            mGLView.render();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
index db5c244..e2688f1 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.content.DialogInterface
 import android.content.Intent
+import android.content.pm.PackageManager
 import android.content.res.ColorStateList
 import android.os.UserHandle
 import android.util.IconDrawableFactory
@@ -157,16 +158,21 @@
         } else {
             icons.visibility = View.GONE
         }
-        item.setOnClickListener(object : View.OnClickListener {
-            val intent = Intent(Intent.ACTION_REVIEW_APP_PERMISSION_USAGE)
-                    .putExtra(Intent.EXTRA_PACKAGE_NAME, app.packageName)
-                    .putExtra(Intent.EXTRA_USER, UserHandle.getUserHandleForUid(app.uid))
-            override fun onClick(v: View?) {
-                Dependency.get(ActivityStarter::class.java)
-                        .postStartActivityDismissingKeyguard(intent, 0)
-                dismissDialog?.invoke()
-            }
-        })
+        try {
+            // Check if package exists
+            context.packageManager.getPackageInfo(app.packageName, 0)
+            item.setOnClickListener(object : View.OnClickListener {
+                val intent = Intent(Intent.ACTION_REVIEW_APP_PERMISSION_USAGE)
+                        .putExtra(Intent.EXTRA_PACKAGE_NAME, app.packageName)
+                        .putExtra(Intent.EXTRA_USER, UserHandle.getUserHandleForUid(app.uid))
+                override fun onClick(v: View?) {
+                    Dependency.get(ActivityStarter::class.java)
+                            .postStartActivityDismissingKeyguard(intent, 0)
+                    dismissDialog?.invoke()
+                }
+            })
+        } catch (e: PackageManager.NameNotFoundException) {}
+
         itemList.addView(item)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index f3a46ce..0583843 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -20,6 +20,8 @@
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
 import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_CHILD_NOTIFICATIONS;
 
+import android.annotation.SuppressLint;
+import android.app.NotificationManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.RemoteException;
@@ -32,10 +34,13 @@
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
 
+import java.util.ArrayList;
+
 /**
  * This class handles listening to notification updates and passing them along to
  * NotificationPresenter to be displayed to the user.
  */
+@SuppressLint("OverrideAbstract")
 public class NotificationListener extends NotificationListenerWithPlugins {
     private static final String TAG = "NotificationListener";
 
@@ -47,6 +52,7 @@
     private final NotificationGroupManager mGroupManager =
             Dependency.get(NotificationGroupManager.class);
 
+    private final ArrayList<NotificationSettingsListener> mSettingsListeners = new ArrayList<>();
     private final Context mContext;
 
     protected NotificationPresenter mPresenter;
@@ -55,6 +61,10 @@
         mContext = context;
     }
 
+    public void addNotificationSettingsListener(NotificationSettingsListener listener) {
+        mSettingsListeners.add(listener);
+    }
+
     @Override
     public void onListenerConnected() {
         if (DEBUG) Log.d(TAG, "onListenerConnected");
@@ -70,6 +80,8 @@
                 mEntryManager.addNotification(sbn, currentRanking);
             }
         });
+        NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
+        onStatusBarIconsBehaviorChanged(noMan.shouldHideSilentStatusBarIcons());
     }
 
     @Override
@@ -133,6 +145,13 @@
         }
     }
 
+    @Override
+    public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+        for (NotificationSettingsListener listener : mSettingsListeners) {
+            listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
+        }
+    }
+
     public void setUpWithPresenter(NotificationPresenter presenter) {
         mPresenter = presenter;
 
@@ -144,4 +163,10 @@
             Log.e(TAG, "Unable to register notification listener", e);
         }
     }
+
+    public interface NotificationSettingsListener {
+
+        default void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { }
+
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index cb1384c..aa221993 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -25,7 +25,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -392,12 +391,6 @@
             return false;
         }
 
-        LogMaker logMaker = (row.getStatusBarNotification() == null)
-                ? new LogMaker(MetricsProto.MetricsEvent.ACTION_NOTE_CONTROLS)
-                : row.getStatusBarNotification().getLogMaker();
-        mMetricsLogger.write(logMaker.setCategory(MetricsProto.MetricsEvent.ACTION_NOTE_CONTROLS)
-                    .setType(MetricsProto.MetricsEvent.TYPE_ACTION));
-
         // ensure that it's laid but not visible until actually laid out
         guts.setVisibility(View.INVISIBLE);
         // Post to ensure the the guts are properly laid out.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 359bc6e..b6948fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -126,18 +126,23 @@
     private OnClickListener mOnKeepShowing = v -> {
         mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
         closeControls(v);
-        mMetricsLogger.write(getLogMaker().setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
-                .setType(MetricsEvent.TYPE_ACTION)
-                .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT));
+        if (mIsForBlockingHelper) {
+            mMetricsLogger.write(getLogMaker().setCategory(
+                    MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
+                    .setType(MetricsEvent.TYPE_ACTION)
+                    .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT));
+        }
     };
 
     private OnClickListener mOnToggleSilent = v -> {
         Runnable saveImportance = () -> {
             swapContent(ACTION_TOGGLE_SILENT, true /* animate */);
-            mMetricsLogger.write(getLogMaker()
-                    .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
-                    .setType(MetricsEvent.TYPE_ACTION)
-                    .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_ALERT_ME));
+            if (mIsForBlockingHelper) {
+                mMetricsLogger.write(getLogMaker()
+                        .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
+                        .setType(MetricsEvent.TYPE_ACTION)
+                        .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_ALERT_ME));
+            }
         };
         if (mCheckSaveListener != null) {
             mCheckSaveListener.checkSave(saveImportance, mSbn);
@@ -149,10 +154,12 @@
     private OnClickListener mOnStopOrMinimizeNotifications = v -> {
         Runnable saveImportance = () -> {
             swapContent(ACTION_BLOCK, true /* animate */);
-            mMetricsLogger.write(getLogMaker()
-                    .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
-                    .setType(MetricsEvent.TYPE_ACTION)
-                    .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_BLOCKED));
+            if (mIsForBlockingHelper) {
+                mMetricsLogger.write(getLogMaker()
+                        .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
+                        .setType(MetricsEvent.TYPE_ACTION)
+                        .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_BLOCKED));
+            }
         };
         if (mCheckSaveListener != null) {
             mCheckSaveListener.checkSave(saveImportance, mSbn);
@@ -164,12 +171,16 @@
     private OnClickListener mOnUndo = v -> {
         // Reset exit counter that we'll log and record an undo event separately (not an exit event)
         mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
-        logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
-        mMetricsLogger.write(importanceChangeLogMaker().setType(MetricsEvent.TYPE_DISMISS));
+        if (mIsForBlockingHelper) {
+            logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
+            mMetricsLogger.write(getLogMaker().setCategory(
+                    MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
+                    .setType(MetricsEvent.TYPE_DISMISS)
+                    .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_UNDO));
+        } else {
+            mMetricsLogger.write(importanceChangeLogMaker().setType(MetricsEvent.TYPE_DISMISS));
+        }
         swapContent(ACTION_UNDO, true /* animate */);
-        mMetricsLogger.write(getLogMaker().setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
-                .setType(MetricsEvent.TYPE_DISMISS)
-                .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_UNDO));
     };
 
     public NotificationInfo(Context context, AttributeSet attrs) {
@@ -269,11 +280,11 @@
         bindPrompt();
         bindButtons();
 
-        mMetricsLogger.write(getLogMaker().setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
-                .setType(MetricsEvent.TYPE_OPEN)
-                .setSubtype(MetricsEvent.BLOCKING_HELPER_DISPLAY));
+        mMetricsLogger.write(notificationControlsLogMaker());
     }
 
+
+
     private void bindHeader() throws RemoteException {
         // Package name
         Drawable pkgicon = null;
@@ -404,19 +415,6 @@
         }
     }
 
-    /**
-     * Returns an initialized LogMaker for logging importance changes.
-     * The caller may override the type (to DISMISS) before passing it to mMetricsLogger.
-     * @return new LogMaker
-     */
-    private LogMaker importanceChangeLogMaker() {
-        Integer chosenImportance =
-                mChosenImportance != null ? mChosenImportance : mStartingChannelImportance;
-        return new LogMaker(MetricsEvent.ACTION_SAVE_IMPORTANCE)
-                .setType(MetricsEvent.TYPE_ACTION)
-                .setSubtype(chosenImportance - mStartingChannelImportance);
-    }
-
     private boolean hasImportanceChanged() {
         return mSingleNotificationChannel != null
                 && mChosenImportance != null
@@ -616,8 +614,8 @@
         confirmation.setAlpha(1f);
         header.setVisibility(VISIBLE);
         header.setAlpha(1f);
-        mMetricsLogger.write(getLogMaker().setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
-                .setType(MetricsEvent.TYPE_CLOSE));
+
+        mMetricsLogger.write(notificationControlsLogMaker().setType(MetricsEvent.TYPE_CLOSE));
     }
 
     @Override
@@ -764,7 +762,39 @@
         }
     }
 
+    /**
+     * Returns a LogMaker with all available notification information.
+     * Caller should set category, type, and maybe subtype, before passing it to mMetricsLogger.
+     * @return LogMaker
+     */
     private LogMaker getLogMaker() {
-        return mSbn.getLogMaker();
+        // The constructor requires a category, so also do it in the other branch for consistency.
+        return mSbn == null ? new LogMaker(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
+                : mSbn.getLogMaker().setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER);
+    }
+
+    /**
+     * Returns an initialized LogMaker for logging importance changes.
+     * The caller may override the type before passing it to mMetricsLogger.
+     * @return LogMaker
+     */
+    private LogMaker importanceChangeLogMaker() {
+        Integer chosenImportance =
+                mChosenImportance != null ? mChosenImportance : mStartingChannelImportance;
+        return getLogMaker().setCategory(MetricsEvent.ACTION_SAVE_IMPORTANCE)
+                .setType(MetricsEvent.TYPE_ACTION)
+                .setSubtype(chosenImportance - mStartingChannelImportance);
+    }
+
+    /**
+     * Returns an initialized LogMaker for logging open/close of the info display.
+     * The caller may override the type before passing it to mMetricsLogger.
+     * @return LogMaker
+     */
+    private LogMaker notificationControlsLogMaker() {
+        return getLogMaker().setCategory(MetricsEvent.ACTION_NOTE_CONTROLS)
+                .setType(MetricsEvent.TYPE_OPEN)
+                .setSubtype(mIsForBlockingHelper ? MetricsEvent.BLOCKING_HELPER_DISPLAY
+                        : MetricsEvent.BLOCKING_HELPER_UNKNOWN);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index e86996a..9e99fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -11,9 +11,7 @@
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
-import androidx.annotation.NonNull;
-import androidx.collection.ArrayMap;
-
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.internal.widget.ViewClippingUtil;
@@ -21,6 +19,7 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarStateController;
@@ -28,11 +27,13 @@
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.tuner.TunerService;
 
 import java.util.ArrayList;
 import java.util.function.Function;
 
+import androidx.annotation.NonNull;
+import androidx.collection.ArrayMap;
+
 /**
  * A controller for the space in the status bar to the left of the system icons. This area is
  * normally reserved for notifications.
@@ -46,18 +47,19 @@
     private final NotificationEntryManager mEntryManager;
     private final Runnable mUpdateStatusBarIcons = this::updateStatusBarIcons;
     private final StatusBarStateController mStatusBarStateController;
-    private final TunerService.Tunable mTunable = new TunerService.Tunable() {
-        @Override
-        public void onTuningChanged(String key, String newValue) {
-            if (key.equals(LOW_PRIORITY)) {
-                mShowLowPriority = "1".equals(newValue)
-                        || !NotificationUtils.useNewInterruptionModel(mContext);
-                if (mNotificationScrollLayout != null) {
-                    updateStatusBarIcons();
+    @VisibleForTesting
+    final NotificationListener.NotificationSettingsListener mSettingsListener =
+            new NotificationListener.NotificationSettingsListener() {
+                @Override
+                public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+                    if (NotificationUtils.useNewInterruptionModel(mContext)) {
+                        mShowLowPriority = !hideSilentStatusIcons;
+                        if (mNotificationScrollLayout != null) {
+                            updateStatusBarIcons();
+                        }
+                    }
                 }
-            }
-        }
-    };
+            };
 
     private int mIconSize;
     private int mIconHPadding;
@@ -71,7 +73,7 @@
     private ViewGroup mNotificationScrollLayout;
     private Context mContext;
     private boolean mFullyDark;
-    private boolean mShowLowPriority;
+    private boolean mShowLowPriority = true;
 
     /**
      * Ratio representing being awake or in ambient mode, where 1 is dark and 0 awake.
@@ -90,15 +92,15 @@
             view -> view instanceof StatusBarWindowView;
 
     public NotificationIconAreaController(Context context, StatusBar statusBar,
-            StatusBarStateController statusBarStateController) {
+            StatusBarStateController statusBarStateController,
+            NotificationListener notificationListener) {
         mStatusBar = statusBar;
         mContrastColorUtil = ContrastColorUtil.getInstance(context);
         mContext = context;
         mEntryManager = Dependency.get(NotificationEntryManager.class);
         mStatusBarStateController = statusBarStateController;
         mStatusBarStateController.addCallback(this);
-
-        Dependency.get(TunerService.class).addTunable(mTunable, LOW_PRIORITY);
+        notificationListener.addNotificationSettingsListener(mSettingsListener);
 
         initializeNotificationAreaViews(context);
     }
@@ -243,6 +245,11 @@
                 true /* hideRepliedMessages */);
     }
 
+    @VisibleForTesting
+    boolean shouldShouldLowPriorityIcons() {
+        return mShowLowPriority;
+    }
+
     /**
      * Updates the notification icons for a host layout. This will ensure that the notification
      * host layout will have the same icons like the ones in here.
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 1470d0f..dd23182 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -480,8 +480,7 @@
             updateAodMaskVisibility(deviceSupportsAodWallpaper && aodImageWallpaperEnabled);
             // If WallpaperInfo is null, it must be ImageWallpaper.
             final boolean supportsAmbientMode = deviceSupportsAodWallpaper
-                    && (info == null && aodImageWallpaperEnabled
-                        || info != null && info.supportsAmbientMode());
+                    && (info == null || info.supportsAmbientMode());
 
             mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
             mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
@@ -801,7 +800,8 @@
         mNotificationLogger.setUpWithContainer(notifListContainer);
 
         mNotificationIconAreaController = SystemUIFactory.getInstance()
-                .createNotificationIconAreaController(context, this, mStatusBarStateController);
+                .createNotificationIconAreaController(
+                        context, this, mStatusBarStateController, mNotificationListener);
         inflateShelf();
         mNotificationIconAreaController.setupShelf(mNotificationShelf);
 
diff --git a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
index 52cabe2..dd1d0ca 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
@@ -156,6 +156,8 @@
 
     private boolean checkIfNeedMask() {
         // We need mask for ImageWallpaper / LockScreen Wallpaper (Music album art).
+        // Because of conflicting with another wallpaper feature,
+        // we only support LockScreen wallpaper currently.
         return mWallpaperManager.getWallpaperInfo() == null || ScrimState.AOD.hasBackdrop();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 6a3bd73..5be8826 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -77,6 +77,10 @@
 
     @Mock
     private NotificationData mNotificationData;
+    @Mock
+    private BubbleController.BubbleStateChangeListener mBubbleStateChangeListener;
+    @Mock
+    private BubbleController.BubbleExpandListener mBubbleExpandListener;
 
     @Before
     public void setUp() throws Exception {
@@ -101,6 +105,8 @@
         when(mNotificationData.getChannel(mNoChannelRow.getEntry().key)).thenReturn(null);
 
         mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController);
+        mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
+        mBubbleController.setExpandListener(mBubbleExpandListener);
 
         // Get a reference to the BubbleController's entry listener
         verify(mNotificationEntryManager, atLeastOnce())
@@ -112,6 +118,8 @@
     public void testAddBubble() {
         mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
         assertTrue(mBubbleController.hasBubbles());
+
+        verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
     }
 
     @Test
@@ -126,10 +134,14 @@
         mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
         assertTrue(mBubbleController.hasBubbles());
 
+        verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
+
         mBubbleController.removeBubble(mRow.getEntry().key);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
         assertTrue(mRow.getEntry().isBubbleDismissed());
         verify(mNotificationEntryManager).updateNotifications();
+
+        verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
     }
 
     @Test
@@ -141,41 +153,133 @@
         mBubbleController.dismissStack();
         assertFalse(mStatusBarWindowController.getBubblesShowing());
         verify(mNotificationEntryManager).updateNotifications();
+        assertTrue(mRow.getEntry().isBubbleDismissed());
+        assertTrue(mRow2.getEntry().isBubbleDismissed());
     }
 
     @Test
-    public void testIsStackExpanded() {
+    public void testExpandCollapseStack() {
         assertFalse(mBubbleController.isStackExpanded());
+
+        // Mark it as a bubble and add it explicitly
+        mEntryListener.onPendingEntryAdded(mRow.getEntry());
         mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
 
+        // We should have bubbles & their notifs should show in the shade
+        assertTrue(mBubbleController.hasBubbles());
+        assertTrue(mRow.getEntry().showInShadeWhenBubble());
+
+        // Expand the stack
         BubbleStackView stackView = mBubbleController.getStackView();
         stackView.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
 
+        // Make sure it's no longer in the shade
+        assertFalse(mRow.getEntry().showInShadeWhenBubble());
+
+        // Collapse
         stackView.collapseStack();
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
         assertFalse(mBubbleController.isStackExpanded());
     }
 
     @Test
-    public void testCollapseStack() {
+    public void testCollapseAfterChangingExpandedBubble() {
+        // Mark it as a bubble and add it explicitly
+        mEntryListener.onPendingEntryAdded(mRow.getEntry());
+        mEntryListener.onPendingEntryAdded(mRow2.getEntry());
         mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
         mBubbleController.updateBubble(mRow2.getEntry(), true /* updatePosition */);
 
+        // We should have bubbles & their notifs should show in the shade
+        assertTrue(mBubbleController.hasBubbles());
+        assertTrue(mRow.getEntry().showInShadeWhenBubble());
+        assertTrue(mRow2.getEntry().showInShadeWhenBubble());
+
+        // Expand
         BubbleStackView stackView = mBubbleController.getStackView();
         stackView.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
 
+        // Last added is the one that is expanded
+        assertEquals(mRow2.getEntry(), stackView.getExpandedBubble().getEntry());
+        assertFalse(mRow2.getEntry().showInShadeWhenBubble());
+
+        // Switch which bubble is expanded
         stackView.setExpandedBubble(mRow.getEntry());
-        assertEquals(stackView.getExpandedBubble().getEntry(), mRow.getEntry());
+        assertEquals(mRow.getEntry(), stackView.getExpandedBubble().getEntry());
+        assertFalse(mRow.getEntry().showInShadeWhenBubble());
 
-        stackView.setExpandedBubble(mRow2.getEntry());
-        assertEquals(stackView.getExpandedBubble().getEntry(), mRow2.getEntry());
+        // collapse for previous bubble
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+        // expand for selected bubble
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
 
+        // Collapse
         mBubbleController.collapseStack();
         assertFalse(mBubbleController.isStackExpanded());
     }
 
     @Test
+    public void testExpansionRemovesShowInShade() {
+        // Mark it as a bubble and add it explicitly
+        mEntryListener.onPendingEntryAdded(mRow.getEntry());
+        mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
+
+        // We should have bubbles & their notifs should show in the shade
+        assertTrue(mBubbleController.hasBubbles());
+        assertTrue(mRow.getEntry().showInShadeWhenBubble());
+
+        // Expand
+        BubbleStackView stackView = mBubbleController.getStackView();
+        stackView.expandStack();
+        assertTrue(mBubbleController.isStackExpanded());
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+
+        // No longer show shade in notif after expansion
+        assertFalse(mRow.getEntry().showInShadeWhenBubble());
+    }
+
+    @Test
+    public void testRemoveLastExpandedCollapses() {
+        // Mark it as a bubble and add it explicitly
+        mEntryListener.onPendingEntryAdded(mRow.getEntry());
+        mEntryListener.onPendingEntryAdded(mRow2.getEntry());
+        mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
+        mBubbleController.updateBubble(mRow2.getEntry(), true /* updatePosition */);
+        verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
+
+        // Expand
+        BubbleStackView stackView = mBubbleController.getStackView();
+        stackView.expandStack();
+
+        assertTrue(mBubbleController.isStackExpanded());
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+
+        // Last added is the one that is expanded
+        assertEquals(mRow2.getEntry(), stackView.getExpandedBubble().getEntry());
+        assertFalse(mRow2.getEntry().showInShadeWhenBubble());
+
+        // Dismiss currently expanded
+        mBubbleController.removeBubble(stackView.getExpandedBubble().getKey());
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+
+        // Make sure next bubble is selected
+        assertEquals(mRow.getEntry(), stackView.getExpandedBubble().getEntry());
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+
+        // Dismiss that one
+        mBubbleController.removeBubble(stackView.getExpandedBubble().getKey());
+
+        // Make sure state changes and collapse happens
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
+        verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
+        assertFalse(mBubbleController.hasBubbles());
+    }
+
+    @Test
     public void testMarkNewNotificationAsBubble() {
         mEntryListener.onPendingEntryAdded(mRow.getEntry());
         assertTrue(mRow.getEntry().isBubble());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
index c880172..bcf5964 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
@@ -17,10 +17,12 @@
 package com.android.systemui.statusbar;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
@@ -55,6 +57,7 @@
     // Dependency mocks:
     @Mock private NotificationEntryManager mEntryManager;
     @Mock private NotificationRemoteInputManager mRemoteInputManager;
+    @Mock private NotificationManager mNotificationManager;
 
     private NotificationListener mListener;
     private StatusBarNotification mSbn;
@@ -67,6 +70,7 @@
                 mRemoteInputManager);
         mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
                 new Handler(TestableLooper.get(this).getLooper()));
+        mContext.addMockSystemService(NotificationManager.class, mNotificationManager);
 
         when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
 
@@ -106,4 +110,28 @@
         // RankingMap may be modified by plugins.
         verify(mEntryManager).updateNotificationRanking(any());
     }
+
+    @Test
+    public void testOnConnectReadStatusBarSetting() {
+        NotificationListener.NotificationSettingsListener settingsListener =
+                mock(NotificationListener.NotificationSettingsListener.class);
+        mListener.addNotificationSettingsListener(settingsListener);
+
+        when(mNotificationManager.shouldHideSilentStatusBarIcons()).thenReturn(true);
+
+        mListener.onListenerConnected();
+
+        verify(settingsListener).onStatusBarIconsBehaviorChanged(true);
+    }
+
+    @Test
+    public void testOnStatusBarIconsBehaviorChanged() {
+        NotificationListener.NotificationSettingsListener settingsListener =
+                mock(NotificationListener.NotificationSettingsListener.class);
+        mListener.addNotificationSettingsListener(settingsListener);
+
+        mListener.onStatusBarIconsBehaviorChanged(true);
+
+        verify(settingsListener).onStatusBarIconsBehaviorChanged(true);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index fdc9e0c..727e9af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -45,7 +45,6 @@
 import android.app.NotificationChannel;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.metrics.LogMaker;
 import android.os.Binder;
 import android.os.Handler;
 import android.provider.Settings;
@@ -57,7 +56,6 @@
 import android.view.View;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.NotificationPresenter;
@@ -220,34 +218,6 @@
     }
 
     @Test
-    public void testOpenGutsLogging() {
-        NotificationGutsManager gutsManager = spy(mGutsManager);
-        doReturn(true).when(gutsManager).bindGuts(any(), any());
-
-        NotificationGuts guts = spy(new NotificationGuts(mContext));
-        doReturn(true).when(guts).post(any());
-
-        ExpandableNotificationRow realRow = createTestNotificationRow();
-        NotificationMenuRowPlugin.MenuItem menuItem = createTestMenuItem(realRow);
-
-        ExpandableNotificationRow row = spy(realRow);
-        when(row.getWindowToken()).thenReturn(new Binder());
-        when(row.getGuts()).thenReturn(guts);
-        StatusBarNotification notification = spy(realRow.getStatusBarNotification());
-        when(row.getStatusBarNotification()).thenReturn(notification);
-
-        assertTrue(gutsManager.openGuts(row, 0, 0, menuItem));
-
-        ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
-        verify(notification).getLogMaker();
-        verify(mMetricsLogger).write(logMakerCaptor.capture());
-        assertEquals(MetricsProto.MetricsEvent.ACTION_NOTE_CONTROLS,
-                logMakerCaptor.getValue().getCategory());
-        assertEquals(MetricsProto.MetricsEvent.TYPE_ACTION,
-                logMakerCaptor.getValue().getType());
-    }
-
-    @Test
     public void testAppOpsSettingsIntent_camera() {
         ArraySet<Integer> ops = new ArraySet<>();
         ops.add(OP_CAMERA);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 554baaf..2a64445 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -83,7 +83,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
@@ -107,11 +106,16 @@
     private NotificationChannel mDefaultNotificationChannel;
     private StatusBarNotification mSbn;
 
-    @Rule public MockitoRule mockito = MockitoJUnit.rule();
-    @Mock private MetricsLogger mMetricsLogger;
-    @Mock private INotificationManager mMockINotificationManager;
-    @Mock private PackageManager mMockPackageManager;
-    @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
+    @Rule
+    public MockitoRule mockito = MockitoJUnit.rule();
+    @Mock
+    private MetricsLogger mMetricsLogger;
+    @Mock
+    private INotificationManager mMockINotificationManager;
+    @Mock
+    private PackageManager mMockPackageManager;
+    @Mock
+    private NotificationBlockingHelperManager mBlockingHelperManager;
 
     @Before
     public void setUp() throws Exception {
@@ -172,44 +176,25 @@
         PollingCheck.waitFor(1000,
                 () -> VISIBLE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility());
     }
+
     private void ensureNoUndoButton() {
         PollingCheck.waitFor(1000,
                 () -> GONE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility()
                         && !mNotificationInfo.isAnimating());
     }
+
     private void waitForStopButton() {
         PollingCheck.waitFor(1000,
                 () -> VISIBLE == mNotificationInfo.findViewById(R.id.prompt).getVisibility());
     }
 
-    class ImportanceChangeLogMaker implements ArgumentMatcher<LogMaker> {
-        private static final int CATEGORY = MetricsProto.MetricsEvent.ACTION_SAVE_IMPORTANCE;
-        private int mType, mSubtype;
-
-        ImportanceChangeLogMaker(int type, int subtype) {
-            mType = type;
-            mSubtype = subtype;
-        }
-        public boolean matches(LogMaker l) {
-            return (l.getCategory() == CATEGORY)
-                    && (l.getType() == mType)
-                    && (l.getSubtype() == mSubtype);
-        }
-
-        public String toString() {
-            return String.format("LogMaker(%d, %d, %d)", CATEGORY, mType, mSubtype);
-        }
-    }
-
-    private LogMaker importanceChangeLog(int type, int subtype) {
-        return argThat(new ImportanceChangeLogMaker(type, subtype));
-    }
-
     @Test
     public void testBindNotification_SetsTextApplicationName() throws Exception {
         when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+                null, null, null,
+                true, false,
                 IMPORTANCE_DEFAULT, true);
         final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
         assertTrue(textView.getText().toString().contains("App Name"));
@@ -330,9 +315,9 @@
 
     @Test
     public void testBindNotification_BlockButton() throws Exception {
-       mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-               TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-               IMPORTANCE_DEFAULT, true);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                IMPORTANCE_DEFAULT, true);
         final View block = mNotificationInfo.findViewById(R.id.int_block);
         final View minimize = mNotificationInfo.findViewById(R.id.block_or_minimize);
         assertEquals(VISIBLE, block.getVisibility());
@@ -340,7 +325,7 @@
     }
 
     @Test
-    public void testBindNotification_BlockButton_BlockHelper() throws Exception {
+    public void testBindNotification_BlockButton_BlockingHelper() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 true /* isBlockingHelper */, false, IMPORTANCE_DEFAULT, true);
@@ -498,13 +483,29 @@
     }
 
     @Test
-    public void testLogBlockingHelperCounter_logGutsViewDisplayed() throws Exception {
+    public void testBindNotificationLogging_notBlockingHelper() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+                null, null, null,
+                true, false,
                 IMPORTANCE_DEFAULT, true);
-        mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
         verify(mMetricsLogger).write(argThat(logMaker ->
-                logMaker.getCategory() == MetricsEvent.NOTIFICATION_BLOCKING_HELPER
+                logMaker.getCategory() == MetricsEvent.ACTION_NOTE_CONTROLS
+                        && logMaker.getType() == MetricsEvent.TYPE_OPEN
+                        && logMaker.getSubtype() == MetricsEvent.BLOCKING_HELPER_UNKNOWN
+        ));
+    }
+
+    @Test
+    public void testBindNotificationLogging_BlockingHelper() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+                null, null, null,
+                false, true,
+                true, true,
+                IMPORTANCE_DEFAULT, true);
+        verify(mMetricsLogger).write(argThat(logMaker ->
+                logMaker.getCategory() == MetricsEvent.ACTION_NOTE_CONTROLS
                         && logMaker.getType() == MetricsEvent.TYPE_OPEN
                         && logMaker.getSubtype() == MetricsEvent.BLOCKING_HELPER_DISPLAY
         ));
@@ -513,8 +514,11 @@
     @Test
     public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
-                true, true, IMPORTANCE_DEFAULT, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+                null, null, null,
+                false, true,
+                true, true,
+                IMPORTANCE_DEFAULT, true);
         mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
         verify(mMetricsLogger).count(eq("HowCanNotifsBeRealIfAppsArent"), eq(1));
     }
@@ -680,7 +684,7 @@
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+                null /* onSettingsClick */, null /* onAppSettingsClick */,
                 true, false /* isNonblockable */, IMPORTANCE_DEFAULT, false
         );
 
@@ -722,7 +726,7 @@
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+                null /* onSettingsClick */, null /* onAppSettingsClick */,
                 true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
                 true /* isUserSentimentNegative */, IMPORTANCE_DEFAULT, true);
@@ -744,14 +748,14 @@
     }
 
     @Test
-    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing()
+    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing_BlockingHelper()
             throws Exception {
         NotificationInfo.CheckSaveListener listener =
                 mock(NotificationInfo.CheckSaveListener.class);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ , true /* provisioned */,
+                null /* onSettingsClick */, null /* onAppSettingsClick */, true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
                 true /* isUserSentimentNegative */, IMPORTANCE_DEFAULT, true);
 
@@ -772,14 +776,14 @@
     }
 
     @Test
-    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss()
+    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss_BlockingHelper()
             throws Exception {
         NotificationInfo.CheckSaveListener listener =
                 mock(NotificationInfo.CheckSaveListener.class);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+                null /* onSettingsClick */, null /* onAppSettingsClick */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
                 true, true /* isUserSentimentNegative */,  /* isNoisy */
                 IMPORTANCE_DEFAULT, true);
@@ -791,7 +795,7 @@
     }
 
     @Test
-    public void testCloseControls_checkSaveListenerDelaysStopNotifications()
+    public void testCloseControls_checkSaveListenerDelaysStopNotifications_BlockingHelper()
             throws Exception {
         NotificationInfo.CheckSaveListener listener =
                 mock(NotificationInfo.CheckSaveListener.class);
@@ -849,18 +853,25 @@
     }
 
     @Test
-    public void testBlockChangedCallsUpdateNotificationChannel() throws Exception {
+    public void testBlockChangedCallsUpdateNotificationChannel_notBlockingHelper()
+            throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+                null, null, null,
+                true, false,
                 IMPORTANCE_DEFAULT, false);
 
         mNotificationInfo.findViewById(R.id.int_block).performClick();
         waitForUndoButton();
         mNotificationInfo.handleCloseControls(true, false);
 
-        verify(mMetricsLogger).write(importanceChangeLog(
-                MetricsProto.MetricsEvent.TYPE_ACTION, IMPORTANCE_NONE - IMPORTANCE_LOW));
+        ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+        verify(mMetricsLogger, times(2)).write(logMakerCaptor.capture());
+        assertEquals(MetricsProto.MetricsEvent.TYPE_ACTION,
+                logMakerCaptor.getValue().getType());
+        assertEquals(IMPORTANCE_NONE - IMPORTANCE_LOW,
+                logMakerCaptor.getValue().getSubtype());
 
         mTestableLooper.processAllMessages();
         ArgumentCaptor<NotificationChannel> updated =
@@ -896,8 +907,12 @@
         waitForUndoButton();
         mNotificationInfo.handleCloseControls(true, false);
 
-        verify(mMetricsLogger).write(importanceChangeLog(
-                MetricsProto.MetricsEvent.TYPE_ACTION, IMPORTANCE_NONE - IMPORTANCE_LOW));
+        ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+        verify(mMetricsLogger, times(3)).write(logMakerCaptor.capture());
+        assertEquals(MetricsProto.MetricsEvent.TYPE_ACTION,
+                logMakerCaptor.getValue().getType());
+        assertEquals(IMPORTANCE_NONE - IMPORTANCE_LOW,
+                logMakerCaptor.getValue().getSubtype());
 
         mTestableLooper.processAllMessages();
         ArgumentCaptor<NotificationChannel> updated =
@@ -965,10 +980,12 @@
     }
 
     @Test
-    public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
+    public void testBlockUndoDoesNotBlockNotificationChannel_notBlockingHelper() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+                null, null, null,
+                true, false,
                 IMPORTANCE_DEFAULT, false);
 
         mNotificationInfo.findViewById(R.id.int_block).performClick();
@@ -977,8 +994,15 @@
         waitForStopButton();
         // mNotificationInfo.handleCloseControls doesn't get called by this interaction.
 
-        verify(mMetricsLogger).write(importanceChangeLog(
-                MetricsProto.MetricsEvent.TYPE_DISMISS, IMPORTANCE_NONE - IMPORTANCE_LOW));
+        ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+        verify(mMetricsLogger, times(2)).write(logMakerCaptor.capture());
+        assertEquals(MetricsEvent.ACTION_SAVE_IMPORTANCE,
+                logMakerCaptor.getValue().getCategory());
+        assertEquals(MetricsEvent.TYPE_DISMISS,
+                logMakerCaptor.getValue().getType());
+        assertEquals(IMPORTANCE_NONE - IMPORTANCE_LOW,
+                logMakerCaptor.getValue().getSubtype());
+
 
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
@@ -986,11 +1010,12 @@
     }
 
     @Test
-    public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
+    public void testMinUndoDoesNotMinNotificationChannel_notBlockingHelper() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
-                IMPORTANCE_DEFAULT, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
+                null, null, null, true,
+                true, IMPORTANCE_DEFAULT, false);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
new file mode 100644
index 0000000..13145b8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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.statusbar.phone;
+
+import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.LightBarTransitionsController.DarkIntensityApplier;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationIconAreaControllerTest extends SysuiTestCase {
+
+    @Mock
+    private NotificationListener mListener;
+    @Mock
+    StatusBar mStatusBar;
+    @Mock
+    StatusBarStateController mStatusBarStateController;
+    private NotificationIconAreaController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        mController = new NotificationIconAreaController(mContext, mStatusBar,
+                mStatusBarStateController, mListener);
+    }
+
+    @Test
+    public void testNotificationIcons_featureOff() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(), NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
+        assertTrue(mController.shouldShouldLowPriorityIcons());
+    }
+
+    @Test
+    public void testNotificationIcons_featureOn_settingHideIcons() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(), NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+        mController.mSettingsListener.onStatusBarIconsBehaviorChanged(true);
+
+        assertFalse(mController.shouldShouldLowPriorityIcons());
+    }
+
+    @Test
+    public void testNotificationIcons_featureOn_settingShowIcons() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(), NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+        mController.mSettingsListener.onStatusBarIconsBehaviorChanged(false);
+
+        assertTrue(mController.shouldShouldLowPriorityIcons());
+    }
+}
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 8172e71..1d0b9b6 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -20,6 +20,7 @@
         package="com.android.vpndialogs">
 
     <uses-permission android:name="android.permission.CONTROL_VPN" />
+    <uses-permission android:name="android.permission.CONTROL_ALWAYS_ON_VPN" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
 
     <application android:label="VpnDialogs"
diff --git a/packages/overlays/FontArbutusSourceOverlay/Android.mk b/packages/overlays/FontArbutusSourceOverlay/Android.mk
deleted file mode 100644
index 23aee55..0000000
--- a/packages/overlays/FontArbutusSourceOverlay/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-#  Copyright 2018, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_RRO_THEME := FontArbutusSource
-LOCAL_CERTIFICATE := platform
-LOCAL_PRODUCT_MODULE := true
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := FontArbutusSourceOverlay
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/FontArbutusSourceOverlay/AndroidManifest.xml b/packages/overlays/FontArbutusSourceOverlay/AndroidManifest.xml
deleted file mode 100644
index 46c06b9..0000000
--- a/packages/overlays/FontArbutusSourceOverlay/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.theme.font.arbutussource"
-    android:versionCode="1"
-    android:versionName="1.0">
-    <overlay android:targetPackage="android"
-        android:category="android.theme.customization.font"
-        android:priority="1"/>
-
-    <application android:label="@string/font_arbutus_source_overlay" android:hasCode="false">
-        <meta-data
-            android:name="android.theme.customization.REQUIRED_SYSTEM_FONTS"
-            android:value="arbutus-slab,source-sans-pro,source-sans-pro-medium" />
-    </application>
-</manifest>
diff --git a/packages/overlays/FontArbutusSourceOverlay/res/values/config.xml b/packages/overlays/FontArbutusSourceOverlay/res/values/config.xml
deleted file mode 100644
index a6aa64c..0000000
--- a/packages/overlays/FontArbutusSourceOverlay/res/values/config.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-     <!-- Name of a font family to use for body text. -->
-    <string name="config_bodyFontFamily" translatable="false">source-sans-pro</string>
-    <!-- Name of a font family to use for medium body text. -->
-    <string name="config_bodyFontFamilyMedium" translatable="false">source-sans-pro-semi-bold</string>
-    <!-- Name of a font family to use for headlines. If empty, falls back to platform default -->
-    <string name="config_headlineFontFamily" translatable="false">arbutus-slab</string>
-    <!-- Name of the font family used for system surfaces where the font should use medium weight -->
-    <string name="config_headlineFontFamilyMedium" translatable="false">arbutus-slab</string>
-</resources>
-
diff --git a/packages/overlays/FontArbutusSourceOverlay/res/values/strings.xml b/packages/overlays/FontArbutusSourceOverlay/res/values/strings.xml
deleted file mode 100644
index d80eb20..0000000
--- a/packages/overlays/FontArbutusSourceOverlay/res/values/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Headline / Body font Arbutus Slab / Source Sans Pro overlay -->
-    <string name="font_arbutus_source_overlay" translatable="false">Arbutus Slab / Source Sans Pro</string>
-</resources>
diff --git a/packages/overlays/FontArvoLatoOverlay/Android.mk b/packages/overlays/FontArvoLatoOverlay/Android.mk
deleted file mode 100644
index 3433ecf..0000000
--- a/packages/overlays/FontArvoLatoOverlay/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-#  Copyright 2018, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_RRO_THEME := FontArvoLato
-LOCAL_CERTIFICATE := platform
-LOCAL_PRODUCT_MODULE := true
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := FontArvoLatoOverlay
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/FontArvoLatoOverlay/AndroidManifest.xml b/packages/overlays/FontArvoLatoOverlay/AndroidManifest.xml
deleted file mode 100644
index 3f2e5de..0000000
--- a/packages/overlays/FontArvoLatoOverlay/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.theme.font.arvolato"
-    android:versionCode="1"
-    android:versionName="1.0">
-    <overlay android:targetPackage="android"
-        android:category="android.theme.customization.font"
-        android:priority="1"/>
-
-    <application android:label="@string/font_arvo_lato_overlay" android:hasCode="false">
-        <meta-data
-            android:name="android.theme.customization.REQUIRED_SYSTEM_FONTS"
-            android:value="arvo,arvo-medium,lato,lato-medium" />
-    </application>
-</manifest>
diff --git a/packages/overlays/FontArvoLatoOverlay/res/values/config.xml b/packages/overlays/FontArvoLatoOverlay/res/values/config.xml
deleted file mode 100644
index 4e70d72..0000000
--- a/packages/overlays/FontArvoLatoOverlay/res/values/config.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-     <!-- Name of a font family to use for body text. -->
-    <string name="config_bodyFontFamily" translatable="false">lato</string>
-    <!-- Name of a font family to use for medium body text. -->
-    <string name="config_bodyFontFamilyMedium" translatable="false">lato-bold</string>
-    <!-- Name of a font family to use for headlines. If empty, falls back to platform default -->
-    <string name="config_headlineFontFamily" translatable="false">arvo</string>
-    <!-- Name of the font family used for system surfaces where the font should use medium weight -->
-    <string name="config_headlineFontFamilyMedium" translatable="false">arvo-bold</string>
-</resources>
-
diff --git a/packages/overlays/FontArvoLatoOverlay/res/values/strings.xml b/packages/overlays/FontArvoLatoOverlay/res/values/strings.xml
deleted file mode 100644
index 9ea097f..0000000
--- a/packages/overlays/FontArvoLatoOverlay/res/values/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Headline / Body font Arvo / Lato overlay -->
-    <string name="font_arvo_lato_overlay" translatable="false">Arvo / Lato</string>
-</resources>
diff --git a/packages/overlays/FontRubikRubikOverlay/Android.mk b/packages/overlays/FontRubikRubikOverlay/Android.mk
deleted file mode 100644
index 21d617e..0000000
--- a/packages/overlays/FontRubikRubikOverlay/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-#  Copyright 2018, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_RRO_THEME := FontRubikRubik
-LOCAL_CERTIFICATE := platform
-LOCAL_PRODUCT_MODULE := true
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := FontRubikRubikOverlay
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/FontRubikRubikOverlay/AndroidManifest.xml b/packages/overlays/FontRubikRubikOverlay/AndroidManifest.xml
deleted file mode 100644
index 1f28d46..0000000
--- a/packages/overlays/FontRubikRubikOverlay/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.theme.font.rubikrubik"
-    android:versionCode="1"
-    android:versionName="1.0">
-    <overlay android:targetPackage="android"
-        android:category="android.theme.customization.font"
-        android:priority="1"/>
-
-    <application android:label="@string/font_rubik_rubik_overlay" android:hasCode="false">
-        <meta-data
-            android:name="android.theme.customization.REQUIRED_SYSTEM_FONTS"
-            android:value="rubik,rubik-medium" />
-    </application>
-</manifest>
diff --git a/packages/overlays/FontRubikRubikOverlay/res/values/config.xml b/packages/overlays/FontRubikRubikOverlay/res/values/config.xml
deleted file mode 100644
index 4f90e29..0000000
--- a/packages/overlays/FontRubikRubikOverlay/res/values/config.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-     <!-- Name of a font family to use for body text. -->
-    <string name="config_bodyFontFamily" translatable="false">rubik</string>
-    <!-- Name of a font family to use for medium body text. -->
-    <string name="config_bodyFontFamilyMedium" translatable="false">rubik-medium</string>
-    <!-- Name of a font family to use for headlines. If empty, falls back to platform default -->
-    <string name="config_headlineFontFamily" translatable="false">rubik</string>
-    <!-- Name of the font family used for system surfaces where the font should use medium weight -->
-    <string name="config_headlineFontFamilyMedium" translatable="false">rubik-medium</string>
-</resources>
-
diff --git a/packages/overlays/FontRubikRubikOverlay/res/values/strings.xml b/packages/overlays/FontRubikRubikOverlay/res/values/strings.xml
deleted file mode 100644
index 4bac7da..0000000
--- a/packages/overlays/FontRubikRubikOverlay/res/values/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Headline / Body font Rubik overlay -->
-    <string name="font_rubik_rubik_overlay" translatable="false">Rubik / Rubik</string>
-</resources>
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 385931d..aeb4261 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6910,6 +6910,11 @@
     // CATEGORY: NOTIFICATION
     FIELD_NOTIFICATION_CATEGORY = 1641;
 
+    // OPEN: Settings > Settings > Network & internet > Click Mobile network to land on page with
+    // details for a SIM/eSIM mobile network > Click edit icon to bring up a rename dialog.
+    // OS: Q
+    MOBILE_NETWORK_RENAME_DIALOG = 1642;
+
     // ---- End Q Constants, all Q constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index f4ac130..fc43882 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -348,8 +348,8 @@
     }
 
     int getRelevantEventTypes() {
-        return (mUsesAccessibilityCache ? AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK : 0)
-                | mEventTypes;
+        return (mUsesAccessibilityCache ? AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK
+                : AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) | mEventTypes;
     }
 
     @Override
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 7d228f1..8b2c1b9 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -1863,7 +1863,7 @@
             // The agent was running with a stub Application object, so shut it down.
             // !!! We hardcode the confirmation UI's package name here rather than use a
             //     manifest flag!  TODO something less direct.
-            if (app.uid >= Process.FIRST_APPLICATION_UID
+            if (!UserHandle.isCore(app.uid)
                     && !app.packageName.equals("com.android.backupconfirm")) {
                 if (MORE_DEBUG) Slog.d(TAG, "Killing agent host process");
                 mActivityManager.killApplicationProcess(app.processName, app.uid);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 7763d7b..324c2d9 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -45,9 +45,9 @@
 import android.os.Bundle;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Slog;
 
@@ -1174,7 +1174,7 @@
                 //     b. the app does not state android:killAfterRestore="false" in its manifest
                 final int appFlags = mCurrentPackage.applicationInfo.flags;
                 final boolean killAfterRestore =
-                        (mCurrentPackage.applicationInfo.uid >= Process.FIRST_APPLICATION_UID)
+                        !UserHandle.isCore(mCurrentPackage.applicationInfo.uid)
                                 && ((mRestoreDescription.getDataType()
                                 == RestoreDescription.TYPE_FULL_STREAM)
                                 || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0));
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 2db8928..7ee3047 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -31,7 +31,6 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Slog;
@@ -72,7 +71,7 @@
         }
 
         // 2. they run as a system-level uid
-        if ((app.uid < Process.FIRST_APPLICATION_UID)) {
+        if (UserHandle.isCore(app.uid)) {
             // and the backup is happening for non-system user
             if (userId != UserHandle.USER_SYSTEM && !app.packageName.equals(
                     PACKAGE_MANAGER_SENTINEL)) {
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index cce5b3b..97bde9c 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -34,7 +34,7 @@
 import android.content.pm.Signature;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.Process;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -162,7 +162,7 @@
                             if (AppBackupUtils.signaturesMatch(sigs, pkg, pmi)) {
                                 // If this is a system-uid app without a declared backup agent,
                                 // don't restore any of the file data.
-                                if ((pkg.applicationInfo.uid < Process.FIRST_APPLICATION_UID)
+                                if (UserHandle.isCore(pkg.applicationInfo.uid)
                                         && (pkg.applicationInfo.backupAgentName == null)) {
                                     Slog.w(TAG, "Installed app " + info.packageName
                                             + " has restricted uid and no agent");
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index f4b235a..f3b8098 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -53,7 +53,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.Bundle;
-import android.os.Process;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.server.backup.FileMetadata;
@@ -404,8 +404,7 @@
             if ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) {
                 // Restore system-uid-space packages only if they have
                 // defined a custom backup agent
-                if ((pkgInfo.applicationInfo.uid
-                        >= Process.FIRST_APPLICATION_UID)
+                if (!UserHandle.isCore(pkgInfo.applicationInfo.uid)
                         || (pkgInfo.applicationInfo.backupAgentName != null)) {
                     // Verify signatures against any installed version; if they
                     // don't match, then we fall though and ignore the data.  The
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index de7c8cc..58263fc 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -146,6 +146,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnInfo;
@@ -2685,6 +2686,11 @@
                     EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE,
                     mNai.network.netId));
         }
+
+        @Override
+        public void logCaptivePortalLoginEvent(int eventId, String packageName) {
+            new MetricsLogger().action(eventId, packageName);
+        }
     }
 
     private boolean networkRequiresValidation(NetworkAgentInfo nai) {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index d2c6354..33c6dd2 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -405,6 +405,7 @@
 
         // initialize in-memory settings values
         onBackgroundThrottleWhitelistChangedLocked();
+        onIgnoreSettingsWhitelistChangedLocked();
     }
 
     @GuardedBy("mLock")
@@ -547,17 +548,16 @@
 
     @GuardedBy("mLock")
     private void onBackgroundThrottleWhitelistChangedLocked() {
-        String setting = Settings.Global.getString(
-                mContext.getContentResolver(),
-                Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
-        if (setting == null) {
-            setting = "";
-        }
-
         mBackgroundThrottlePackageWhitelist.clear();
         mBackgroundThrottlePackageWhitelist.addAll(
                 SystemConfig.getInstance().getAllowUnthrottledLocation());
-        mBackgroundThrottlePackageWhitelist.addAll(Arrays.asList(setting.split(",")));
+
+        String setting = Settings.Global.getString(
+                mContext.getContentResolver(),
+                Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
+        if (!TextUtils.isEmpty(setting)) {
+            mBackgroundThrottlePackageWhitelist.addAll(Arrays.asList(setting.split(",")));
+        }
 
         for (LocationProvider p : mProviders) {
             applyRequirementsLocked(p);
@@ -566,17 +566,16 @@
 
     @GuardedBy("lock")
     private void onIgnoreSettingsWhitelistChangedLocked() {
-        String setting = Settings.Global.getString(
-                mContext.getContentResolver(),
-                Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST);
-        if (setting == null) {
-            setting = "";
-        }
-
         mIgnoreSettingsPackageWhitelist.clear();
         mIgnoreSettingsPackageWhitelist.addAll(
                 SystemConfig.getInstance().getAllowIgnoreLocationSettings());
-        mIgnoreSettingsPackageWhitelist.addAll(Arrays.asList(setting.split(",")));
+
+        String setting = Settings.Global.getString(
+                mContext.getContentResolver(),
+                Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST);
+        if (!TextUtils.isEmpty(setting)) {
+            mIgnoreSettingsPackageWhitelist.addAll(Arrays.asList(setting.split(",")));
+        }
 
         for (LocationProvider p : mProviders) {
             applyRequirementsLocked(p);
@@ -2200,7 +2199,7 @@
             return false;
         }
 
-        if (mBackgroundThrottlePackageWhitelist.contains(record.mReceiver.mIdentity.mPackageName)) {
+        if (mIgnoreSettingsPackageWhitelist.contains(record.mReceiver.mIdentity.mPackageName)) {
             return true;
         }
 
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index cecd55a3..f2329d3 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1541,10 +1541,6 @@
         mCallbacks = new Callbacks(FgThread.get().getLooper());
         mLockPatternUtils = new LockPatternUtils(mContext);
 
-        mPmInternal = LocalServices.getService(PackageManagerInternal.class);
-        mUmInternal = LocalServices.getService(UserManagerInternal.class);
-        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
-
         HandlerThread hthread = new HandlerThread(TAG);
         hthread.start();
         mHandler = new StorageManagerServiceHandler(hthread.getLooper());
@@ -1662,6 +1658,19 @@
     }
 
     private void servicesReady() {
+        mPmInternal = LocalServices.getService(PackageManagerInternal.class);
+        mUmInternal = LocalServices.getService(UserManagerInternal.class);
+        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
+
+        mIPackageManager = IPackageManager.Stub.asInterface(
+                ServiceManager.getService("package"));
+        mIAppOpsService = IAppOpsService.Stub.asInterface(
+                ServiceManager.getService(Context.APP_OPS_SERVICE));
+        try {
+            mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
+        } catch (RemoteException e) {
+        }
+
         synchronized (mLock) {
             final boolean thisIsolatedStorage = StorageManager.hasIsolatedStorage();
             if (mLastIsolatedStorage == thisIsolatedStorage) {
@@ -1734,14 +1743,6 @@
                 .registerScreenObserver(this);
 
         mSystemReady = true;
-        mIPackageManager = IPackageManager.Stub.asInterface(
-                ServiceManager.getService("package"));
-        mIAppOpsService = IAppOpsService.Stub.asInterface(
-                ServiceManager.getService(Context.APP_OPS_SERVICE));
-        try {
-            mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
-        } catch (RemoteException e) {
-        }
         mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
     }
 
diff --git a/services/core/java/com/android/server/ThreadPriorityBooster.java b/services/core/java/com/android/server/ThreadPriorityBooster.java
index 53e8ce4..f74a4385 100644
--- a/services/core/java/com/android/server/ThreadPriorityBooster.java
+++ b/services/core/java/com/android/server/ThreadPriorityBooster.java
@@ -43,9 +43,9 @@
 
     public void boost() {
         final int tid = myTid();
-        final int prevPriority = getThreadPriority(tid);
         final PriorityState state = mThreadState.get();
         if (state.regionCounter == 0) {
+            final int prevPriority = getThreadPriority(tid);
             state.prevPriority = prevPriority;
             if (prevPriority > mBoostToPriority) {
                 setThreadPriority(tid, mBoostToPriority);
@@ -60,9 +60,11 @@
     public void reset() {
         final PriorityState state = mThreadState.get();
         state.regionCounter--;
-        final int currentPriority = getThreadPriority(myTid());
-        if (state.regionCounter == 0 && state.prevPriority != currentPriority) {
-            setThreadPriority(myTid(), state.prevPriority);
+        if (state.regionCounter == 0) {
+            final int currentPriority = getThreadPriority(myTid());
+            if (state.prevPriority != currentPriority) {
+                setThreadPriority(myTid(), state.prevPriority);
+            }
         }
     }
 
@@ -77,9 +79,11 @@
         mBoostToPriority = priority;
         final PriorityState state = mThreadState.get();
         final int tid = myTid();
-        final int prevPriority = getThreadPriority(tid);
-        if (state.regionCounter != 0 && prevPriority != priority) {
-            setThreadPriority(tid, priority);
+        if (state.regionCounter != 0) {
+            final int prevPriority = getThreadPriority(tid);
+            if (prevPriority != priority) {
+                setThreadPriority(tid, priority);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index f6e698f..9b9911a 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -593,7 +593,7 @@
                 Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg, reason);
                 if (mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
                         > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
-                        && vib.isHapticFeedback()) {
+                        && !vib.isNotification() && !vib.isRingtone()) {
                     Slog.e(TAG, "Ignoring incoming vibration as process with uid = "
                             + uid + " is background");
                     return;
diff --git a/services/core/java/com/android/server/am/ActiveInstrumentation.java b/services/core/java/com/android/server/am/ActiveInstrumentation.java
index 15de3de..9510f59 100644
--- a/services/core/java/com/android/server/am/ActiveInstrumentation.java
+++ b/services/core/java/com/android/server/am/ActiveInstrumentation.java
@@ -49,6 +49,9 @@
     // Connection to use the UI introspection APIs.
     IUiAutomationConnection mUiAutomationConnection;
 
+    // Whether the caller holds START_ACTIVITIES_FROM_BACKGROUND permission
+    boolean mHasBackgroundActivityStartsPermission;
+
     // As given to us
     Bundle mArguments;
 
@@ -117,6 +120,8 @@
             pw.print(prefix); pw.print("mUiAutomationConnection=");
             pw.println(mUiAutomationConnection);
         }
+        pw.print("mHasBackgroundActivityStartsPermission=");
+        pw.println(mHasBackgroundActivityStartsPermission);
         pw.print(prefix); pw.print("mArguments=");
         pw.println(mArguments);
     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bec7386..66e9eb3a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -22,6 +22,7 @@
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.Manifest.permission.REMOVE_TASKS;
+import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
 import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
 import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
 import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
@@ -2217,7 +2218,7 @@
         mConstants = hasHandlerThread ? new ActivityManagerConstants(this, mHandler) : null;
         final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */);
         mProcessList.init(this, activeUids);
-        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
+        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, new Object());
 
         mIntentFirewall = hasHandlerThread
                 ? new IntentFirewall(new IntentFirewallInterface(), mHandler) : null;
@@ -2265,7 +2266,7 @@
         mConstants = new ActivityManagerConstants(this, mHandler);
         final ActiveUids activeUids = new ActiveUids(this, true /* postChangesToAtm */);
         mProcessList.init(this, activeUids);
-        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
+        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, atm.getGlobalLock());
 
         // Broadcast policy parameters
         final BroadcastConstants foreConstants = new BroadcastConstants(
@@ -3091,7 +3092,7 @@
                 } else {
                     UidRecord validateUid = mValidateUids.get(item.uid);
                     if (validateUid == null) {
-                        validateUid = new UidRecord(item.uid, mAtmInternal);
+                        validateUid = new UidRecord(item.uid);
                         mValidateUids.put(item.uid, validateUid);
                     }
                     if ((item.change & UidRecord.CHANGE_IDLE) != 0) {
@@ -15195,7 +15196,9 @@
             IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection,
             int userId, String abiOverride) {
         enforceNotIsolatedCaller("startInstrumentation");
-        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+        final int callingUid = Binder.getCallingUid();
+        final int callingPid = Binder.getCallingPid();
+        userId = mUserController.handleIncomingUser(callingPid, callingUid,
                 userId, false, ALLOW_FULL_ONLY, "startInstrumentation", null);
         // Refuse possible leaked file descriptors
         if (arguments != null && arguments.hasFileDescriptors()) {
@@ -15260,6 +15263,9 @@
             activeInstr.mWatcher = watcher;
             activeInstr.mUiAutomationConnection = uiAutomationConnection;
             activeInstr.mResultClass = className;
+            activeInstr.mHasBackgroundActivityStartsPermission = checkPermission(
+                    START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
+                            == PackageManager.PERMISSION_GRANTED;
 
             boolean disableHiddenApiChecks = ai.usesNonSdkApi()
                     || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java
index bb55ec31..1118014 100644
--- a/services/core/java/com/android/server/am/AppCompactor.java
+++ b/services/core/java/com/android/server/am/AppCompactor.java
@@ -19,6 +19,7 @@
 import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_ACTION_1;
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_ACTION_2;
+import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_STATSD_SAMPLE_RATE;
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_1;
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_2;
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_3;
@@ -45,6 +46,7 @@
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Random;
 
 public final class AppCompactor {
 
@@ -65,6 +67,8 @@
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_4 = 10_000;
+    // The sampling rate to push app compaction events into statsd for upload.
+    @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f;
 
     @VisibleForTesting
     interface PropertyChangedCallbackForTest {
@@ -104,6 +108,8 @@
                                 || KEY_COMPACT_THROTTLE_3.equals(name)
                                 || KEY_COMPACT_THROTTLE_4.equals(name)) {
                             updateCompactionThrottles();
+                        } else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
+                            updateStatsdSampleRate();
                         }
                     }
                     if (mTestCallback != null) {
@@ -116,21 +122,25 @@
 
     // Configured by phenotype. Updates from the server take effect immediately.
     @GuardedBy("mPhenotypeFlagLock")
-    @VisibleForTesting String mCompactActionSome =
+    @VisibleForTesting volatile String mCompactActionSome =
             compactActionIntToString(DEFAULT_COMPACT_ACTION_1);
     @GuardedBy("mPhenotypeFlagLock")
-    @VisibleForTesting String mCompactActionFull =
+    @VisibleForTesting volatile String mCompactActionFull =
             compactActionIntToString(DEFAULT_COMPACT_ACTION_2);
     @GuardedBy("mPhenotypeFlagLock")
-    @VisibleForTesting long mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
+    @VisibleForTesting volatile long mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
     @GuardedBy("mPhenotypeFlagLock")
-    @VisibleForTesting long mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
+    @VisibleForTesting volatile long mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
     @GuardedBy("mPhenotypeFlagLock")
-    @VisibleForTesting long mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
+    @VisibleForTesting volatile long mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
     @GuardedBy("mPhenotypeFlagLock")
-    @VisibleForTesting long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
+    @VisibleForTesting volatile long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
     @GuardedBy("mPhenotypeFlagLock")
-    private boolean mUseCompaction = DEFAULT_USE_COMPACTION;
+    private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
+
+    private final Random mRandom = new Random();
+    @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting volatile float mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
 
     // Handler on which compaction runs.
     private Handler mCompactionHandler;
@@ -158,6 +168,7 @@
             updateUseCompaction();
             updateCompactionActions();
             updateCompactionThrottles();
+            updateStatsdSampleRate();
         }
     }
 
@@ -181,6 +192,7 @@
             pw.println("  " + KEY_COMPACT_THROTTLE_2 + "=" + mCompactThrottleSomeFull);
             pw.println("  " + KEY_COMPACT_THROTTLE_3 + "=" + mCompactThrottleFullSome);
             pw.println("  " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull);
+            pw.println("  " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mStatsdSampleRate);
         }
     }
 
@@ -289,6 +301,19 @@
         }
     }
 
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateStatsdSampleRate() {
+        String sampleRateFlag = DeviceConfig.getProperty(DeviceConfig.ActivityManager.NAMESPACE,
+                KEY_COMPACT_STATSD_SAMPLE_RATE);
+        try {
+            mStatsdSampleRate = TextUtils.isEmpty(sampleRateFlag)
+                    ? DEFAULT_STATSD_SAMPLE_RATE : Float.parseFloat(sampleRateFlag);
+        } catch (NumberFormatException e) {
+            mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
+        }
+        mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate));
+    }
+
     @VisibleForTesting
     static String compactActionIntToString(int action) {
         switch(action) {
@@ -385,11 +410,16 @@
                                 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
                                 rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
                                 lastCompactAction, lastCompactTime, msg.arg1, msg.arg2);
-                        StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
-                                rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
-                                rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
-                                lastCompactAction, lastCompactTime, msg.arg1,
-                                ActivityManager.processStateAmToProto(msg.arg2));
+                        // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
+                        // on every single compaction for a flag that will seldom change and the
+                        // impact of reading the wrong value here is low.
+                        if (mRandom.nextFloat() < mStatsdSampleRate) {
+                            StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
+                                    rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
+                                    rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
+                                    lastCompactAction, lastCompactTime, msg.arg1,
+                                    ActivityManager.processStateAmToProto(msg.arg2));
+                        }
                         synchronized (mAm) {
                             proc.lastCompactTime = end;
                             proc.lastCompactAction = pendingAction;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 64a36ef..1fb11ba 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -450,7 +450,7 @@
         if (state == BroadcastRecord.IDLE) {
             Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
         }
-        if (r.allowBackgroundActivityStarts) {
+        if (r.allowBackgroundActivityStarts && r.curApp != null) {
             r.curApp.removeAllowBackgroundActivityStartsToken(r);
          }
         // If we're abandoning this broadcast before any receivers were actually spun up,
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 6e8646e..4985c52 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -127,8 +127,18 @@
     private final ActivityManagerService mService;
     private final ProcessList mProcessList;
 
-    OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
+    /**
+     * Used to lock {@link #updateOomAdjImpl} for state consistency. It also reduces frequency lock
+     * and unlock when getting and setting value to {@link ProcessRecord#mWindowProcessController}.
+     * Note it is declared as Object type so the locked-region-code-injection won't wrap the
+     * unnecessary priority booster.
+     */
+    private final Object mAtmGlobalLock;
+
+    OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids,
+            Object atmGlobalLock) {
         mService = service;
+        mAtmGlobalLock = atmGlobalLock;
         mProcessList = processList;
         mActiveUids = activeUids;
 
@@ -186,6 +196,13 @@
 
     @GuardedBy("mService")
     final void updateOomAdjLocked() {
+        synchronized (mAtmGlobalLock) {
+            updateOomAdjImpl();
+        }
+    }
+
+    @GuardedBy({"mService", "mAtmGlobalLock"})
+    private void updateOomAdjImpl() {
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "updateOomAdj");
         mService.mOomAdjProfiler.oomAdjStarted();
         final ProcessRecord TOP_APP = mService.getTopAppLocked();
@@ -534,6 +551,7 @@
                 uidRec.setProcState = uidRec.getCurProcState();
                 uidRec.setWhitelist = uidRec.curWhitelist;
                 uidRec.setIdle = uidRec.idle;
+                mService.mAtmInternal.onUidProcStateChanged(uidRec.uid, uidRec.setProcState);
                 mService.enqueueUidChangeLocked(uidRec, -1, uidChange);
                 mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState());
                 if (uidRec.foregroundServices) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 4aa71f9..49c4bc4 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2197,7 +2197,7 @@
         }
         UidRecord uidRec = mActiveUids.get(proc.uid);
         if (uidRec == null) {
-            uidRec = new UidRecord(proc.uid, mService.mAtmInternal);
+            uidRec = new UidRecord(proc.uid);
             // This is the first appearance of the uid, report it now!
             if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                     "Creating new process uid: " + uidRec);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 7ae77d5..6161f7d 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -655,10 +655,6 @@
         return mWindowProcessController.hasActivities();
     }
 
-    void clearActivities() {
-        mWindowProcessController.clearActivities();
-    }
-
     boolean hasActivitiesOrRecentTasks() {
         return mWindowProcessController.hasActivitiesOrRecentTasks();
     }
@@ -667,10 +663,6 @@
         return mWindowProcessController.hasRecentTasks();
     }
 
-    void clearRecentTasks() {
-        mWindowProcessController.clearRecentTasks();
-    }
-
     /**
      * This method returns true if any of the activities within the process record are interesting
      * to the user. See HistoryRecord.isInterestingToUserLocked()
@@ -1181,6 +1173,8 @@
     void setActiveInstrumentation(ActiveInstrumentation instr) {
         mInstr = instr;
         mWindowProcessController.setInstrumenting(instr != null);
+        mWindowProcessController.setInstrumentingWithBackgroundActivityStartPrivileges(instr != null
+                && instr.mHasBackgroundActivityStartsPermission);
     }
 
     ActiveInstrumentation getActiveInstrumentation() {
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 5c60900..e731f34 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -77,6 +77,7 @@
     // permission in the corresponding .te file your feature belongs to.
     @VisibleForTesting
     static final String[] sDeviceConfigScopes = new String[] {
+        DeviceConfig.ActivityManagerNativeBoot.NAMESPACE,
         DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_NETD_NATIVE,
         DeviceConfig.RuntimeNative.NAMESPACE,
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 6cb1097..22a7de7 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -26,7 +26,6 @@
 import android.util.proto.ProtoUtils;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.server.wm.ActivityTaskManagerInternal;
 
 /**
  * Overall information about a uid that has actively running processes.
@@ -43,7 +42,6 @@
     boolean idle;
     boolean setIdle;
     int numProcs;
-    final ActivityTaskManagerInternal mAtmInternal;
 
     /**
      * Sequence number associated with the {@link #mCurProcState}. This is incremented using
@@ -117,10 +115,9 @@
     ChangeItem pendingChange;
     int lastReportedChange;
 
-    public UidRecord(int _uid, ActivityTaskManagerInternal atmInternal) {
+    public UidRecord(int _uid) {
         uid = _uid;
         idle = true;
-        mAtmInternal = atmInternal;
         reset();
     }
 
@@ -130,9 +127,6 @@
 
     public void setCurProcState(int curProcState) {
         mCurProcState = curProcState;
-        if (mAtmInternal != null) {
-            mAtmInternal.onUidProcStateChanged(uid, curProcState);
-        }
     }
 
     public void reset() {
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 5b469fe..2061b26 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -16,9 +16,9 @@
 
 package com.android.server.attention;
 
+import static android.provider.DeviceConfig.AttentionManagerService.COMPONENT_NAME;
 import static android.provider.DeviceConfig.AttentionManagerService.NAMESPACE;
-import static android.provider.DeviceConfig.AttentionManagerService.PROPERTY_COMPONENT_NAME;
-import static android.provider.DeviceConfig.AttentionManagerService.PROPERTY_SERVICE_ENABLED;
+import static android.provider.DeviceConfig.AttentionManagerService.SERVICE_ENABLED;
 
 import android.Manifest;
 import android.annotation.Nullable;
@@ -129,7 +129,7 @@
     }
 
     private boolean isServiceEnabled() {
-        final String enabled = DeviceConfig.getProperty(NAMESPACE, PROPERTY_SERVICE_ENABLED);
+        final String enabled = DeviceConfig.getProperty(NAMESPACE, SERVICE_ENABLED);
         return enabled == null ? DEFAULT_SERVICE_ENABLED : "true".equals(enabled);
     }
 
@@ -279,7 +279,7 @@
      * system.
      */
     private static ComponentName resolveAttentionService(Context context) {
-        final String flag = DeviceConfig.getProperty(NAMESPACE, PROPERTY_COMPONENT_NAME);
+        final String flag = DeviceConfig.getProperty(NAMESPACE, COMPONENT_NAME);
 
         final String componentNameString = flag != null ? flag : context.getString(
                 R.string.config_defaultAttentionService);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index d652f93..deaa931 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -600,7 +600,7 @@
                     break;
                 case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
                     mDeviceInventory.onSetA2dpSinkConnectionState(
-                            (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1, msg.arg2);
+                            (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
                     break;
                 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
                     mDeviceInventory.onSetA2dpSourceConnectionState(
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index eb76e6e0..97649a7 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -147,18 +147,20 @@
     }
 
     /*package*/ void onSetA2dpSinkConnectionState(@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo,
-            @AudioService.BtProfileConnectionState int state, int a2dpVolume) {
+            @AudioService.BtProfileConnectionState int state) {
         final BluetoothDevice btDevice = btInfo.getBtDevice();
+        int a2dpVolume = btInfo.getVolume();
         if (AudioService.DEBUG_DEVICES) {
             Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice + " state="
-                    + state + " is dock=" + btDevice.isBluetoothDock());
+                    + state + " is dock=" + btDevice.isBluetoothDock() + " vol=" + a2dpVolume);
         }
         String address = btDevice.getAddress();
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
             address = "";
         }
         AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
-                "A2DP sink connected: device addr=" + address + " state=" + state));
+                "A2DP sink connected: device addr=" + address + " state=" + state
+                        + " vol=" + a2dpVolume));
 
         final int a2dpCodec;
         synchronized (mDeviceBroker.mA2dpAvrcpLock) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index df33bf2..1723163 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -392,12 +392,14 @@
     * e.g. user on homescreen, no app playing anything, presses hardware volume buttons, this
     *    stream type is controlled.
     */
-   protected static final int DEFAULT_VOL_STREAM_NO_PLAYBACK = AudioSystem.STREAM_MUSIC;
+    protected static final int DEFAULT_VOL_STREAM_NO_PLAYBACK = AudioSystem.STREAM_MUSIC;
 
     private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
         public void onError(int error) {
             switch (error) {
             case AudioSystem.AUDIO_STATUS_SERVER_DIED:
+                mRecordMonitor.clear();
+
                 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
                         SENDMSG_NOOP, 0, 0, null, 0);
                 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
index 9d6628c..b2c7ff3 100644
--- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -78,24 +78,27 @@
                 updateSnapshot(event, uid, session, source, recordingInfo,
                 portId, silenced, activeSource, clientEffects, effects);
         if (configsSystem != null){
-            synchronized (mClients) {
-                // list of recording configurations for "public consumption". It is only computed if
-                // there are non-system recording activity listeners.
-                final List<AudioRecordingConfiguration> configsPublic = mHasPublicClients ?
-                        anonymizeForPublicConsumption(configsSystem) :
-                            new ArrayList<AudioRecordingConfiguration>();
-                final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
-                while (clientIterator.hasNext()) {
-                    final RecMonitorClient rmc = clientIterator.next();
-                    try {
-                        if (rmc.mIsPrivileged) {
-                            rmc.mDispatcherCb.dispatchRecordingConfigChange(configsSystem);
-                        } else {
-                            rmc.mDispatcherCb.dispatchRecordingConfigChange(configsPublic);
-                        }
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Could not call dispatchRecordingConfigChange() on client", e);
+            dispatchCallbacks(configsSystem);
+        }
+    }
+    private void dispatchCallbacks(List<AudioRecordingConfiguration> configs) {
+        synchronized (mClients) {
+            // list of recording configurations for "public consumption". It is only computed if
+            // there are non-system recording activity listeners.
+            final List<AudioRecordingConfiguration> configsPublic = mHasPublicClients
+                    ? anonymizeForPublicConsumption(configs) :
+                      new ArrayList<AudioRecordingConfiguration>();
+            final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
+            while (clientIterator.hasNext()) {
+                final RecMonitorClient rmc = clientIterator.next();
+                try {
+                    if (rmc.mIsPrivileged) {
+                        rmc.mDispatcherCb.dispatchRecordingConfigChange(configs);
+                    } else {
+                        rmc.mDispatcherCb.dispatchRecordingConfigChange(configsPublic);
                     }
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Could not call dispatchRecordingConfigChange() on client", e);
                 }
             }
         }
@@ -130,6 +133,13 @@
         AudioSystem.setRecordingCallback(this);
     }
 
+    void clear() {
+        synchronized (mRecordConfigs) {
+            mRecordConfigs.clear();
+        }
+        dispatchCallbacks(new ArrayList<AudioRecordingConfiguration>());
+    }
+
     void registerRecordingCallback(IRecordingConfigDispatcher rcdb, boolean isPrivileged) {
         if (rcdb == null) {
             return;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 7e95f10..e1af81b 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -166,6 +166,7 @@
     private final NetworkInfo mNetworkInfo;
     private String mPackage;
     private int mOwnerUID;
+    private boolean mIsPackageTargetingAtLeastQ;
     private String mInterface;
     private Connection mConnection;
     private LegacyVpnRunner mLegacyVpnRunner;
@@ -227,6 +228,7 @@
 
         mPackage = VpnConfig.LEGACY_VPN;
         mOwnerUID = getAppUid(mPackage, mUserHandle);
+        mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage);
 
         try {
             netService.registerObserver(mObserver);
@@ -268,8 +270,11 @@
 
     public void updateCapabilities() {
         final Network[] underlyingNetworks = (mConfig != null) ? mConfig.underlyingNetworks : null;
+        // Only apps targeting Q and above can explicitly declare themselves as metered.
+        final boolean isAlwaysMetered =
+                mIsPackageTargetingAtLeastQ && (mConfig == null || mConfig.isMetered);
         updateCapabilities(mContext.getSystemService(ConnectivityManager.class), underlyingNetworks,
-                mNetworkCapabilities);
+                mNetworkCapabilities, isAlwaysMetered);
 
         if (mNetworkAgent != null) {
             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
@@ -278,11 +283,13 @@
 
     @VisibleForTesting
     public static void updateCapabilities(ConnectivityManager cm, Network[] underlyingNetworks,
-            NetworkCapabilities caps) {
+            NetworkCapabilities caps, boolean isAlwaysMetered) {
         int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
         int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
-        boolean metered = false;
+        // VPN's meteredness is OR'd with isAlwaysMetered and meteredness of its underlying
+        // networks.
+        boolean metered = isAlwaysMetered;
         boolean roaming = false;
         boolean congested = false;
 
@@ -725,6 +732,7 @@
             Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
             mPackage = newPackage;
             mOwnerUID = getAppUid(newPackage, mUserHandle);
+            mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage);
             try {
                 mNetd.allowProtect(mOwnerUID);
             } catch (Exception e) {
@@ -790,6 +798,21 @@
         return result;
     }
 
+    private boolean doesPackageTargetAtLeastQ(String packageName) {
+        if (VpnConfig.LEGACY_VPN.equals(packageName)) {
+            return true;
+        }
+        PackageManager pm = mContext.getPackageManager();
+        try {
+            ApplicationInfo appInfo =
+                    pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserHandle);
+            return appInfo.targetSdkVersion >= VERSION_CODES.Q;
+        } catch (NameNotFoundException unused) {
+            Log.w(TAG, "Can't find \"" + packageName + "\"");
+            return false;
+        }
+    }
+
     public NetworkInfo getNetworkInfo() {
         return mNetworkInfo;
     }
@@ -1078,6 +1101,8 @@
                 // as rules are deleted. This prevents data leakage as the rules are moved over.
                 agentDisconnect(oldNetworkAgent);
             }
+            // Set up VPN's capabilities such as meteredness.
+            updateCapabilities();
 
             if (oldConnection != null) {
                 mContext.unbindService(oldConnection);
@@ -1778,6 +1803,7 @@
         config.user = profile.key;
         config.interfaze = iface;
         config.session = profile.name;
+        config.isMetered = false;
 
         config.addLegacyRoutes(profile.routes);
         if (!profile.dnsServers.isEmpty()) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b89768a..c9df86e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1241,27 +1241,59 @@
         }
     }
 
+    @Nullable
+    private IBinder getDisplayToken(int displayId) {
+        synchronized (mSyncRoot) {
+            final LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null) {
+                final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
+                if (device != null) {
+                    return device.getDisplayTokenLocked();
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private boolean screenshotInternal(int displayId, Surface outSurface) {
+        final IBinder token = getDisplayToken(displayId);
+        if (token == null) {
+            return false;
+        }
+        SurfaceControl.screenshot(token, outSurface);
+        return true;
+    }
+
     @VisibleForTesting
     DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributesInternal(
             int displayId) {
-        IBinder displayToken = SurfaceControl.getBuiltInDisplay(displayId);
-        return SurfaceControl.getDisplayedContentSamplingAttributes(displayToken);
+        final IBinder token = getDisplayToken(displayId);
+        if (token == null) {
+            return null;
+        }
+        return SurfaceControl.getDisplayedContentSamplingAttributes(token);
     }
 
     @VisibleForTesting
     boolean setDisplayedContentSamplingEnabledInternal(
             int displayId, boolean enable, int componentMask, int maxFrames) {
-        IBinder displayToken = SurfaceControl.getBuiltInDisplay(displayId);
+        final IBinder token = getDisplayToken(displayId);
+        if (token == null) {
+            return false;
+        }
         return SurfaceControl.setDisplayedContentSamplingEnabled(
-                displayToken, enable, componentMask, maxFrames);
+                token, enable, componentMask, maxFrames);
     }
 
     @VisibleForTesting
     DisplayedContentSample getDisplayedContentSampleInternal(int displayId,
             long maxFrames, long timestamp) {
-        IBinder displayToken = SurfaceControl.getBuiltInDisplay(displayId);
-        return SurfaceControl.getDisplayedContentSample(
-            displayToken, maxFrames, timestamp);
+        final IBinder token = getDisplayToken(displayId);
+        if (token == null) {
+            return null;
+        }
+        return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp);
     }
 
     private void clearViewportsLocked() {
@@ -2257,20 +2289,7 @@
 
         @Override
         public boolean screenshot(int displayId, Surface outSurface) {
-            synchronized (mSyncRoot) {
-                final LogicalDisplay display = mLogicalDisplays.get(displayId);
-                if (display != null) {
-                    final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
-                    if (device != null) {
-                        final IBinder token = device.getDisplayTokenLocked();
-                        if (token != null) {
-                            SurfaceControl.screenshot(token, outSurface);
-                            return true;
-                        }
-                    }
-                }
-            }
-            return false;
+            return screenshotInternal(displayId, outSurface);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index db3928e..2a8462b 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -592,6 +592,9 @@
     }
 
     public BrightnessConfiguration getDefaultBrightnessConfiguration() {
+        if (mAutomaticBrightnessController == null) {
+            return null;
+        }
         return mAutomaticBrightnessController.getDefaultConfig();
     }
 
diff --git a/services/core/java/com/android/server/dreams/OWNERS b/services/core/java/com/android/server/dreams/OWNERS
index 3c9bbf8..426f002 100644
--- a/services/core/java/com/android/server/dreams/OWNERS
+++ b/services/core/java/com/android/server/dreams/OWNERS
@@ -1,3 +1,3 @@
-dsandler@google.com
+dsandler@android.com
 michaelwr@google.com
 roosa@google.com
diff --git a/services/core/java/com/android/server/incident/IncidentCompanionService.java b/services/core/java/com/android/server/incident/IncidentCompanionService.java
index 3ebba00..6f2bfc3 100644
--- a/services/core/java/com/android/server/incident/IncidentCompanionService.java
+++ b/services/core/java/com/android/server/incident/IncidentCompanionService.java
@@ -16,38 +16,18 @@
 
 package com.android.server.incident;
 
-import android.app.ActivityManager;
-import android.app.AppOpsManager;
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.net.Uri;
 import android.os.Binder;
-import android.os.Handler;
 import android.os.IIncidentAuthListener;
 import android.os.IIncidentCompanion;
-import android.os.IncidentManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
 
 import com.android.internal.util.DumpUtils;
 import com.android.server.SystemService;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 
-// TODO: User changes should deny everything that's pending.
-
 /**
  * Helper service for incidentd and dumpstated to provide user feedback
  * and authorization for bug and inicdent reports to be taken.
@@ -55,83 +35,26 @@
 public class IncidentCompanionService extends SystemService {
     static final String TAG = "IncidentCompanionService";
 
-    private final Handler mHandler = new Handler();
-    private final RequestQueue mRequestQueue = new RequestQueue(mHandler);
-    private final PackageManager mPackageManager;
-    private final AppOpsManager mAppOpsManager;
-
-    //
-    // All fields below must be protected by mLock
-    //
-    private final Object mLock = new Object();
-    private final ArrayList<PendingReportRec> mPending = new ArrayList();
-
     /**
-     * The next ID we'll use when we make a PendingReportRec.
+     * Tracker for reports pending approval.
      */
-    private int mNextPendingId = 1;
-
-    /**
-     * One for each authorization that's pending.
-     */
-    private final class PendingReportRec {
-        public int id;
-        public String callingPackage;
-        public int flags;
-        public IIncidentAuthListener listener;
-        public long addedRealtime;
-        public long addedWalltime;
-
-        /**
-         * Construct a PendingReportRec, with an auto-incremented id.
-         */
-        PendingReportRec(String callingPackage, int flags, IIncidentAuthListener listener) {
-            this.id = mNextPendingId++;
-            this.callingPackage = callingPackage;
-            this.flags = flags;
-            this.listener = listener;
-            this.addedRealtime = SystemClock.elapsedRealtime();
-            this.addedWalltime = System.currentTimeMillis();
-        }
-
-        /**
-         * Get the Uri that contains the flattened data.
-         */
-        Uri getUri() {
-            return (new Uri.Builder())
-                    .scheme(IncidentManager.URI_SCHEME)
-                    .authority(IncidentManager.URI_AUTHORITY)
-                    .path(IncidentManager.URI_PATH)
-                    .appendQueryParameter(IncidentManager.URI_PARAM_ID, Integer.toString(id))
-                    .appendQueryParameter(IncidentManager.URI_PARAM_CALLING_PACKAGE, callingPackage)
-                    .appendQueryParameter(IncidentManager.URI_PARAM_FLAGS, Integer.toString(flags))
-                    .appendQueryParameter(IncidentManager.URI_PARAM_TIMESTAMP,
-                            Long.toString(addedWalltime))
-                    .build();
-        }
-    }
+    private PendingReports mPendingReports;
 
     /**
      * Implementation of the IIncidentCompanion binder interface.
      */
     private final class BinderService extends IIncidentCompanion.Stub {
         /**
-         * ONEWAY binder call to initiate authorizing the report.  The actual logic is posted
-         * to mRequestQueue, and may happen later.  The security checks need to happen here.
+         * ONEWAY binder call to initiate authorizing the report.
          */
         @Override
-        public void authorizeReport(int callingUid, final String callingPackage, final int flags,
+        public void authorizeReport(int callingUid, final String callingPackage, int flags,
                 final IIncidentAuthListener listener) {
             enforceRequestAuthorizationPermission();
 
             final long ident = Binder.clearCallingIdentity();
             try {
-                // Starting the system server is complicated, and rather than try to
-                // have a complicated lifecycle that we share with dumpstated and incidentd,
-                // we will accept the request, and then display it whenever it becomes possible to.
-                mRequestQueue.enqueue(listener.asBinder(), true, () -> {
-                    authorizeReportImpl(callingUid, callingPackage, flags, listener);
-                });
+                mPendingReports.authorizeReport(callingUid, callingPackage, flags, listener);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -152,9 +75,7 @@
             // authorize/cancel pairs.
             final long ident = Binder.clearCallingIdentity();
             try {
-                mRequestQueue.enqueue(listener.asBinder(), false, () -> {
-                    cancelReportImpl(listener);
-                });
+                mPendingReports.cancelAuthorization(listener);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -167,19 +88,11 @@
         @Override
         public List<String> getPendingReports() {
             enforceAuthorizePermission();
-
-            synchronized (mLock) {
-                final int size = mPending.size();
-                final ArrayList<String> result = new ArrayList(size);
-                for (int i = 0; i < size; i++) {
-                    result.add(mPending.get(i).getUri().toString());
-                }
-                return result;
-            }
+            return mPendingReports.getPendingReports();
         }
 
         /**
-         * ONEWAY binder call to mark a report as approved.
+         * SYNCHRONOUS binder call to mark a report as approved.
          */
         @Override
         public void approveReport(String uri) {
@@ -187,32 +100,14 @@
 
             final long ident = Binder.clearCallingIdentity();
             try {
-                final PendingReportRec rec;
-                synchronized (mLock) {
-                    rec = findAndRemovePendingReportRecLocked(uri);
-                    if (rec == null) {
-                        Log.e(TAG, "confirmApproved: Couldn't find record for uri: " + uri);
-                        return;
-                    }
-                }
-
-                // Re-do the broadcast, so whoever is listening knows the list changed,
-                // in case another one was added in the meantime.
-                sendBroadcast();
-
-                Log.i(TAG, "Approved report: " + uri);
-                try {
-                    rec.listener.onReportApproved();
-                } catch (RemoteException ex) {
-                    Log.w(TAG, "Failed calling back for approval for: " + uri, ex);
-                }
+                mPendingReports.approveReport(uri);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         }
 
         /**
-         * ONEWAY binder call to mark a report as NOT approved.
+         * SYNCHRONOUS binder call to mark a report as NOT approved.
          */
         @Override
         public void denyReport(String uri) {
@@ -220,25 +115,7 @@
 
             final long ident = Binder.clearCallingIdentity();
             try {
-                final PendingReportRec rec;
-                synchronized (mLock) {
-                    rec = findAndRemovePendingReportRecLocked(uri);
-                    if (rec == null) {
-                        Log.e(TAG, "confirmDenied: Couldn't find record for uri: " + uri);
-                        return;
-                    }
-                }
-
-                // Re-do the broadcast, so whoever is listening knows the list changed,
-                // in case another one was added in the meantime.
-                sendBroadcast();
-
-                Log.i(TAG, "Denied report: " + uri);
-                try {
-                    rec.listener.onReportDenied();
-                } catch (RemoteException ex) {
-                    Log.w(TAG, "Failed calling back for denial for: " + uri, ex);
-                }
+                mPendingReports.denyReport(uri);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -252,27 +129,22 @@
             if (!DumpUtils.checkDumpPermission(getContext(), TAG, writer)) {
                 return;
             }
-            if (args.length == 0) {
-                // Standard text dumpsys
-                final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
-                synchronized (mLock) {
-                    final int size = mPending.size();
-                    writer.println("mPending: (" + size + ")");
-                    for (int i = 0; i < size; i++) {
-                        final PendingReportRec entry = mPending.get(i);
-                        writer.println(String.format("  %11d %s: %s", entry.addedRealtime,
-                                    df.format(new Date(entry.addedWalltime)),
-                                    entry.getUri().toString()));
-                    }
-                }
-            }
+            mPendingReports.dump(fd, writer, args);
         }
 
+        /**
+         * Inside the binder interface class because we want to do all of the authorization
+         * here, before calling out to the helper objects.
+         */
         private void enforceRequestAuthorizationPermission() {
             getContext().enforceCallingOrSelfPermission(
                     android.Manifest.permission.REQUEST_INCIDENT_REPORT_APPROVAL, null);
         }
 
+        /**
+         * Inside the binder interface class because we want to do all of the authorization
+         * here, before calling out to the helper objects.
+         */
         private void enforceAuthorizePermission() {
             getContext().enforceCallingOrSelfPermission(
                     android.Manifest.permission.APPROVE_INCIDENT_REPORTS, null);
@@ -285,8 +157,7 @@
      */
     public IncidentCompanionService(Context context) {
         super(context);
-        mPackageManager = context.getPackageManager();
-        mAppOpsManager = context.getSystemService(AppOpsManager.class);
+        mPendingReports = new PendingReports(context);
     }
 
     /**
@@ -307,239 +178,9 @@
         super.onBootPhase(phase);
         switch (phase) {
             case SystemService.PHASE_BOOT_COMPLETED:
-                // Release the enqueued work.
-                mRequestQueue.start();
+                mPendingReports.onBootCompleted();
                 break;
         }
     }
-
-    /**
-     * Start the confirmation process.
-     */
-    private void authorizeReportImpl(int callingUid, final String callingPackage, int flags,
-            final IIncidentAuthListener listener) {
-        // Enforce that the calling package pertains to the callingUid.
-        if (!isPackageInUid(callingUid, callingPackage)) {
-            Log.w(TAG, "Calling uid " + callingUid + " doesn't match package "
-                    + callingPackage);
-            denyReportBeforeAddingRec(listener, callingPackage);
-            return;
-        }
-
-        // Find the primary user of this device.
-        final int primaryUser = getAndValidateUser();
-        if (primaryUser == UserHandle.USER_NULL) {
-            denyReportBeforeAddingRec(listener, callingPackage);
-            return;
-        }
-
-        // Find the approver app (hint: it's PermissionController).
-        final ComponentName receiver = getApproverComponent(primaryUser);
-        if (receiver == null) {
-            // We couldn't find an approver... so deny the request here and now, before we
-            // do anything else.
-            denyReportBeforeAddingRec(listener, callingPackage);
-            return;
-        }
-
-        // Save the record for when the PermissionController comes back to authorize it.
-        PendingReportRec rec = null;
-        synchronized (mLock) {
-            rec = new PendingReportRec(callingPackage, flags, listener);
-            mPending.add(rec);
-        }
-
-        try {
-            listener.asBinder().linkToDeath(() -> {
-                Log.i(TAG, "Got death notification listener=" + listener);
-                cancelReportImpl(listener, receiver, primaryUser);
-            }, 0);
-        } catch (RemoteException ex) {
-            Log.e(TAG, "Remote died while trying to register death listener: " + rec.getUri());
-            // First, remove from our list.
-            cancelReportImpl(listener, receiver, primaryUser);
-        }
-
-        // Go tell Permission controller to start asking the user.
-        sendBroadcast(receiver, primaryUser);
-    }
-
-    /**
-     * Cancel a pending report request (because of an explicit call to cancel)
-     */
-    private void cancelReportImpl(IIncidentAuthListener listener) {
-        final int primaryUser = getAndValidateUser();
-        final ComponentName receiver = getApproverComponent(primaryUser);
-        if (primaryUser != UserHandle.USER_NULL && receiver != null) {
-            cancelReportImpl(listener, receiver, primaryUser);
-        }
-    }
-
-    /**
-     * Cancel a pending report request (either because of an explicit call to cancel
-     * by the calling app, or because of a binder death).
-     */
-    private void cancelReportImpl(IIncidentAuthListener listener, ComponentName receiver,
-            int primaryUser) {
-        // First, remove from our list.
-        synchronized (mLock) {
-            removePendingReportRecLocked(listener);
-        }
-        // Second, call back to PermissionController to say it's canceled.
-        sendBroadcast(receiver, primaryUser);
-    }
-
-    /**
-     * Send an extra copy of the broadcast, to tell them that the list has changed
-     * because of an addition or removal.  This function is less aggressive than
-     * authorizeReportImpl in logging about failures, because this is for use in
-     * cleanup cases to keep the apps' list in sync with ours.
-     */
-    private void sendBroadcast() {
-        final int primaryUser = getAndValidateUser();
-        if (primaryUser == UserHandle.USER_NULL) {
-            return;
-        }
-        final ComponentName receiver = getApproverComponent(primaryUser);
-        if (receiver == null) {
-            return;
-        }
-        sendBroadcast(receiver, primaryUser);
-    }
-
-    /**
-     * Send the confirmation broadcast.
-     */
-    private void sendBroadcast(ComponentName receiver, int primaryUser) {
-        final Intent intent = new Intent(Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED);
-        intent.setComponent(receiver);
-
-        // Send it to the primary user.
-        getContext().sendBroadcastAsUser(intent, UserHandle.getUserHandleForUid(primaryUser),
-                android.Manifest.permission.APPROVE_INCIDENT_REPORTS);
-    }
-
-    /**
-     * Remove a PendingReportRec keyed by uri, and return it.
-     */
-    private PendingReportRec findAndRemovePendingReportRecLocked(String uriString) {
-        final Uri uri = Uri.parse(uriString);
-        final int id;
-        try {
-            final String idStr = uri.getQueryParameter(IncidentManager.URI_PARAM_ID);
-            id = Integer.parseInt(idStr);
-        } catch (NumberFormatException ex) {
-            Log.w(TAG, "Can't parse id from: " + uriString);
-            return null;
-        }
-        final int size = mPending.size();
-        for (int i = 0; i < size; i++) {
-            final PendingReportRec rec = mPending.get(i);
-            if (rec.id == id) {
-                mPending.remove(i);
-                return rec;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Remove a PendingReportRec keyed by listener.
-     */
-    private void removePendingReportRecLocked(IIncidentAuthListener listener) {
-        final int size = mPending.size();
-        for (int i = 0; i < size; i++) {
-            final PendingReportRec rec = mPending.get(i);
-            if (rec.listener.asBinder() == listener.asBinder()) {
-                Log.i(TAG, "  ...Removed PendingReportRec index=" + i + ": " + rec.getUri());
-                mPending.remove(i);
-            }
-        }
-    }
-
-    /**
-     * Just call listener.deny() (wrapping the RemoteException), without try to
-     * add it to the list.
-     */
-    private void denyReportBeforeAddingRec(IIncidentAuthListener listener, String pkg) {
-        try {
-            listener.onReportDenied();
-        } catch (RemoteException ex) {
-            Log.w(TAG, "Failed calling back for denial for " + pkg, ex);
-        }
-    }
-
-    /**
-     * Check whether the current user is the primary user, and return the user id if they are.
-     * Returns UserHandle.USER_NULL if not valid.
-     */
-    private int getAndValidateUser() {
-        // Current user
-        UserInfo currentUser;
-        try {
-            currentUser = ActivityManager.getService().getCurrentUser();
-        } catch (RemoteException ex) {
-            // We're already inside the system process.
-            throw new RuntimeException(ex);
-        }
-
-        // Primary user
-        final UserManager um = UserManager.get(getContext());
-        final UserInfo primaryUser = um.getPrimaryUser();
-
-        // Check that we're using the right user.
-        if (currentUser == null) {
-            Log.w(TAG, "No current user.  Nobody to approve the report."
-                    + " The report will be denied.");
-            return UserHandle.USER_NULL;
-        }
-        if (primaryUser == null) {
-            Log.w(TAG, "No primary user.  Nobody to approve the report."
-                    + " The report will be denied.");
-            return UserHandle.USER_NULL;
-        }
-        if (primaryUser.id != currentUser.id) {
-            Log.w(TAG, "Only the primary user can approve bugreports, but they are not"
-                    + " the current user. The report will be denied.");
-            return UserHandle.USER_NULL;
-        }
-
-        return primaryUser.id;
-    }
-
-    /**
-     * Return the ComponentName of the BroadcastReceiver that will approve reports.
-     * The system must have zero or one of these installed.  We only look on the
-     * system partition.  When the broadcast happens, the component will also need
-     * have the APPROVE_INCIDENT_REPORTS permission.
-     */
-    private ComponentName getApproverComponent(int userId) {
-        // Find the one true BroadcastReceiver
-        final Intent intent = new Intent(Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED);
-        final List<ResolveInfo> matches = mPackageManager.queryBroadcastReceiversAsUser(intent,
-                PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE
-                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
-        if (matches.size() == 1) {
-            return matches.get(0).getComponentInfo().getComponentName();
-        } else {
-            Log.w(TAG, "Didn't find exactly one BroadcastReceiver to handle "
-                    + Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED
-                    + ". The report will be denied. size="
-                    + matches.size() + ": matches=" + matches);
-            return null;
-        }
-    }
-
-    /**
-     * Return whether the package is one of the packages installed for the uid.
-     */
-    private boolean isPackageInUid(int uid, String packageName) {
-        try {
-            mAppOpsManager.checkPackage(uid, packageName);
-            return true;
-        } catch (SecurityException ex) {
-            return false;
-        }
-    }
 }
 
diff --git a/services/core/java/com/android/server/incident/PendingReports.java b/services/core/java/com/android/server/incident/PendingReports.java
new file mode 100644
index 0000000..519ed41
--- /dev/null
+++ b/services/core/java/com/android/server/incident/PendingReports.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2019 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.incident;
+
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IIncidentAuthListener;
+import android.os.IncidentManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+// TODO: User changes should deny everything that's pending.
+
+/**
+ * Tracker for reports pending approval.
+ */
+class PendingReports {
+    static final String TAG = IncidentCompanionService.TAG;
+
+    private final Handler mHandler = new Handler();
+    private final RequestQueue mRequestQueue = new RequestQueue(mHandler);
+    private final Context mContext;
+    private final PackageManager mPackageManager;
+    private final AppOpsManager mAppOpsManager;
+
+    //
+    // All fields below must be protected by mLock
+    //
+    private final Object mLock = new Object();
+    private final ArrayList<PendingReportRec> mPending = new ArrayList();
+
+    /**
+     * The next ID we'll use when we make a PendingReportRec.
+     */
+    private int mNextPendingId = 1;
+
+    /**
+     * One for each authorization that's pending.
+     */
+    private final class PendingReportRec {
+        public int id;
+        public String callingPackage;
+        public int flags;
+        public IIncidentAuthListener listener;
+        public long addedRealtime;
+        public long addedWalltime;
+
+        /**
+         * Construct a PendingReportRec, with an auto-incremented id.
+         */
+        PendingReportRec(String callingPackage, int flags, IIncidentAuthListener listener) {
+            this.id = mNextPendingId++;
+            this.callingPackage = callingPackage;
+            this.flags = flags;
+            this.listener = listener;
+            this.addedRealtime = SystemClock.elapsedRealtime();
+            this.addedWalltime = System.currentTimeMillis();
+        }
+
+        /**
+         * Get the Uri that contains the flattened data.
+         */
+        Uri getUri() {
+            return (new Uri.Builder())
+                    .scheme(IncidentManager.URI_SCHEME)
+                    .authority(IncidentManager.URI_AUTHORITY)
+                    .path(IncidentManager.URI_PATH)
+                    .appendQueryParameter(IncidentManager.URI_PARAM_ID, Integer.toString(id))
+                    .appendQueryParameter(IncidentManager.URI_PARAM_CALLING_PACKAGE, callingPackage)
+                    .appendQueryParameter(IncidentManager.URI_PARAM_FLAGS, Integer.toString(flags))
+                    .appendQueryParameter(IncidentManager.URI_PARAM_TIMESTAMP,
+                            Long.toString(addedWalltime))
+                    .build();
+        }
+    }
+
+    /**
+     * Construct new PendingReports with the context.
+     */
+    PendingReports(Context context) {
+        mContext = context;
+        mPackageManager = context.getPackageManager();
+        mAppOpsManager = context.getSystemService(AppOpsManager.class);
+    }
+
+    /**
+     * ONEWAY binder call to initiate authorizing the report.  The actual logic is posted
+     * to mRequestQueue, and may happen later.
+     * <p>
+     * The security checks are handled by IncidentCompanionService.
+     */
+    public void authorizeReport(int callingUid, final String callingPackage, final int flags,
+            final IIncidentAuthListener listener) {
+        // Starting the system server is complicated, and rather than try to
+        // have a complicated lifecycle that we share with dumpstated and incidentd,
+        // we will accept the request, and then display it whenever it becomes possible to.
+        mRequestQueue.enqueue(listener.asBinder(), true, () -> {
+            authorizeReportImpl(callingUid, callingPackage, flags, listener);
+        });
+    }
+
+    /**
+     * ONEWAY binder call to cancel the inbound authorization request.
+     * <p>
+     * This is a oneway call, and so is authorizeReport, so the
+     * caller's ordering is preserved.  The other calls on this object are synchronous, so
+     * their ordering is not guaranteed with respect to these calls.  So the implementation
+     * sends out extra broadcasts to allow for eventual consistency.
+     * <p>
+     * The security checks are handled by IncidentCompanionService.
+     */
+    public void cancelAuthorization(final IIncidentAuthListener listener) {
+        mRequestQueue.enqueue(listener.asBinder(), false, () -> {
+            cancelReportImpl(listener);
+        });
+    }
+
+    /**
+     * SYNCHRONOUS binder call to get the list of reports that are pending confirmation
+     * by the user.
+     * <p>
+     * The security checks are handled by IncidentCompanionService.
+     */
+    public List<String> getPendingReports() {
+        synchronized (mLock) {
+            final int size = mPending.size();
+            final ArrayList<String> result = new ArrayList(size);
+            for (int i = 0; i < size; i++) {
+                result.add(mPending.get(i).getUri().toString());
+            }
+            return result;
+        }
+    }
+
+    /**
+     * SYNCHRONOUS binder call to mark a report as approved.
+     * <p>
+     * The security checks are handled by IncidentCompanionService.
+     */
+    public void approveReport(String uri) {
+        final PendingReportRec rec;
+        synchronized (mLock) {
+            rec = findAndRemovePendingReportRecLocked(uri);
+            if (rec == null) {
+                Log.e(TAG, "confirmApproved: Couldn't find record for uri: " + uri);
+                return;
+            }
+        }
+
+        // Re-do the broadcast, so whoever is listening knows the list changed,
+        // in case another one was added in the meantime.
+        sendBroadcast();
+
+        Log.i(TAG, "Approved report: " + uri);
+        try {
+            rec.listener.onReportApproved();
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Failed calling back for approval for: " + uri, ex);
+        }
+    }
+
+    /**
+     * SYNCHRONOUS binder call to mark a report as NOT approved.
+     */
+    public void denyReport(String uri) {
+        final PendingReportRec rec;
+        synchronized (mLock) {
+            rec = findAndRemovePendingReportRecLocked(uri);
+            if (rec == null) {
+                Log.e(TAG, "confirmDenied: Couldn't find record for uri: " + uri);
+                return;
+            }
+        }
+
+        // Re-do the broadcast, so whoever is listening knows the list changed,
+        // in case another one was added in the meantime.
+        sendBroadcast();
+
+        Log.i(TAG, "Denied report: " + uri);
+        try {
+            rec.listener.onReportDenied();
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Failed calling back for denial for: " + uri, ex);
+        }
+    }
+
+    /**
+     * Implementation of adb shell dumpsys debugreportcompanion.
+     */
+    protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
+        if (args.length == 0) {
+            // Standard text dumpsys
+            final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+            synchronized (mLock) {
+                final int size = mPending.size();
+                writer.println("mPending: (" + size + ")");
+                for (int i = 0; i < size; i++) {
+                    final PendingReportRec entry = mPending.get(i);
+                    writer.println(String.format("  %11d %s: %s", entry.addedRealtime,
+                                df.format(new Date(entry.addedWalltime)),
+                                entry.getUri().toString()));
+                }
+            }
+        }
+    }
+
+    /**
+     * Handle the boot process... Starts everything running once the system is
+     * up enough for us to do UI.
+     */
+    public void onBootCompleted() {
+        // Release the enqueued work.
+        mRequestQueue.start();
+    }
+
+    /**
+     * Start the confirmation process.
+     */
+    private void authorizeReportImpl(int callingUid, final String callingPackage, int flags,
+            final IIncidentAuthListener listener) {
+        // Enforce that the calling package pertains to the callingUid.
+        if (!isPackageInUid(callingUid, callingPackage)) {
+            Log.w(TAG, "Calling uid " + callingUid + " doesn't match package "
+                    + callingPackage);
+            denyReportBeforeAddingRec(listener, callingPackage);
+            return;
+        }
+
+        // Find the primary user of this device.
+        final int primaryUser = getAndValidateUser();
+        if (primaryUser == UserHandle.USER_NULL) {
+            denyReportBeforeAddingRec(listener, callingPackage);
+            return;
+        }
+
+        // Find the approver app (hint: it's PermissionController).
+        final ComponentName receiver = getApproverComponent(primaryUser);
+        if (receiver == null) {
+            // We couldn't find an approver... so deny the request here and now, before we
+            // do anything else.
+            denyReportBeforeAddingRec(listener, callingPackage);
+            return;
+        }
+
+        // Save the record for when the PermissionController comes back to authorize it.
+        PendingReportRec rec = null;
+        synchronized (mLock) {
+            rec = new PendingReportRec(callingPackage, flags, listener);
+            mPending.add(rec);
+        }
+
+        try {
+            listener.asBinder().linkToDeath(() -> {
+                Log.i(TAG, "Got death notification listener=" + listener);
+                cancelReportImpl(listener, receiver, primaryUser);
+            }, 0);
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Remote died while trying to register death listener: " + rec.getUri());
+            // First, remove from our list.
+            cancelReportImpl(listener, receiver, primaryUser);
+        }
+
+        // Go tell Permission controller to start asking the user.
+        sendBroadcast(receiver, primaryUser);
+    }
+
+    /**
+     * Cancel a pending report request (because of an explicit call to cancel)
+     */
+    private void cancelReportImpl(IIncidentAuthListener listener) {
+        final int primaryUser = getAndValidateUser();
+        final ComponentName receiver = getApproverComponent(primaryUser);
+        if (primaryUser != UserHandle.USER_NULL && receiver != null) {
+            cancelReportImpl(listener, receiver, primaryUser);
+        }
+    }
+
+    /**
+     * Cancel a pending report request (either because of an explicit call to cancel
+     * by the calling app, or because of a binder death).
+     */
+    private void cancelReportImpl(IIncidentAuthListener listener, ComponentName receiver,
+            int primaryUser) {
+        // First, remove from our list.
+        synchronized (mLock) {
+            removePendingReportRecLocked(listener);
+        }
+        // Second, call back to PermissionController to say it's canceled.
+        sendBroadcast(receiver, primaryUser);
+    }
+
+    /**
+     * Send an extra copy of the broadcast, to tell them that the list has changed
+     * because of an addition or removal.  This function is less aggressive than
+     * authorizeReportImpl in logging about failures, because this is for use in
+     * cleanup cases to keep the apps' list in sync with ours.
+     */
+    private void sendBroadcast() {
+        final int primaryUser = getAndValidateUser();
+        if (primaryUser == UserHandle.USER_NULL) {
+            return;
+        }
+        final ComponentName receiver = getApproverComponent(primaryUser);
+        if (receiver == null) {
+            return;
+        }
+        sendBroadcast(receiver, primaryUser);
+    }
+
+    /**
+     * Send the confirmation broadcast.
+     */
+    private void sendBroadcast(ComponentName receiver, int primaryUser) {
+        final Intent intent = new Intent(Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED);
+        intent.setComponent(receiver);
+
+        // Send it to the primary user.
+        mContext.sendBroadcastAsUser(intent, UserHandle.getUserHandleForUid(primaryUser),
+                android.Manifest.permission.APPROVE_INCIDENT_REPORTS);
+    }
+
+    /**
+     * Remove a PendingReportRec keyed by uri, and return it.
+     */
+    private PendingReportRec findAndRemovePendingReportRecLocked(String uriString) {
+        final Uri uri = Uri.parse(uriString);
+        final int id;
+        try {
+            final String idStr = uri.getQueryParameter(IncidentManager.URI_PARAM_ID);
+            id = Integer.parseInt(idStr);
+        } catch (NumberFormatException ex) {
+            Log.w(TAG, "Can't parse id from: " + uriString);
+            return null;
+        }
+        final int size = mPending.size();
+        for (int i = 0; i < size; i++) {
+            final PendingReportRec rec = mPending.get(i);
+            if (rec.id == id) {
+                mPending.remove(i);
+                return rec;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Remove a PendingReportRec keyed by listener.
+     */
+    private void removePendingReportRecLocked(IIncidentAuthListener listener) {
+        final int size = mPending.size();
+        for (int i = 0; i < size; i++) {
+            final PendingReportRec rec = mPending.get(i);
+            if (rec.listener.asBinder() == listener.asBinder()) {
+                Log.i(TAG, "  ...Removed PendingReportRec index=" + i + ": " + rec.getUri());
+                mPending.remove(i);
+            }
+        }
+    }
+
+    /**
+     * Just call listener.deny() (wrapping the RemoteException), without try to
+     * add it to the list.
+     */
+    private void denyReportBeforeAddingRec(IIncidentAuthListener listener, String pkg) {
+        try {
+            listener.onReportDenied();
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Failed calling back for denial for " + pkg, ex);
+        }
+    }
+
+    /**
+     * Check whether the current user is the primary user, and return the user id if they are.
+     * Returns UserHandle.USER_NULL if not valid.
+     */
+    private int getAndValidateUser() {
+        // Current user
+        UserInfo currentUser;
+        try {
+            currentUser = ActivityManager.getService().getCurrentUser();
+        } catch (RemoteException ex) {
+            // We're already inside the system process.
+            throw new RuntimeException(ex);
+        }
+
+        // Primary user
+        final UserManager um = UserManager.get(mContext);
+        final UserInfo primaryUser = um.getPrimaryUser();
+
+        // Check that we're using the right user.
+        if (currentUser == null) {
+            Log.w(TAG, "No current user.  Nobody to approve the report."
+                    + " The report will be denied.");
+            return UserHandle.USER_NULL;
+        }
+        if (primaryUser == null) {
+            Log.w(TAG, "No primary user.  Nobody to approve the report."
+                    + " The report will be denied.");
+            return UserHandle.USER_NULL;
+        }
+        if (primaryUser.id != currentUser.id) {
+            Log.w(TAG, "Only the primary user can approve bugreports, but they are not"
+                    + " the current user. The report will be denied.");
+            return UserHandle.USER_NULL;
+        }
+
+        return primaryUser.id;
+    }
+
+    /**
+     * Return the ComponentName of the BroadcastReceiver that will approve reports.
+     * The system must have zero or one of these installed.  We only look on the
+     * system partition.  When the broadcast happens, the component will also need
+     * have the APPROVE_INCIDENT_REPORTS permission.
+     */
+    private ComponentName getApproverComponent(int userId) {
+        // Find the one true BroadcastReceiver
+        final Intent intent = new Intent(Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED);
+        final List<ResolveInfo> matches = mPackageManager.queryBroadcastReceiversAsUser(intent,
+                PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+        if (matches.size() == 1) {
+            return matches.get(0).getComponentInfo().getComponentName();
+        } else {
+            Log.w(TAG, "Didn't find exactly one BroadcastReceiver to handle "
+                    + Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED
+                    + ". The report will be denied. size="
+                    + matches.size() + ": matches=" + matches);
+            return null;
+        }
+    }
+
+    /**
+     * Return whether the package is one of the packages installed for the uid.
+     */
+    private boolean isPackageInUid(int uid, String packageName) {
+        try {
+            mAppOpsManager.checkPackage(uid, packageName);
+            return true;
+        } catch (SecurityException ex) {
+            return false;
+        }
+    }
+}
+
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 669ff2b..5e7ea05 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -234,6 +234,7 @@
     private static native void nativeReloadPointerIcons(long ptr);
     private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
     private static native void nativeSetPointerCapture(long ptr, boolean detached);
+    private static native boolean nativeCanDispatchToDisplay(long ptr, int deviceId, int displayId);
 
     // Input event injection constants defined in InputDispatcher.h.
     private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -1890,6 +1891,16 @@
         return new String[0];
     }
 
+    /**
+     * Gets if an input device could dispatch to the given display".
+     * @param deviceId The input device id.
+     * @param displayId The specific display id.
+     * @return True if the device could dispatch to the given display, false otherwise.
+     */
+    public boolean canDispatchToDisplay(int deviceId, int displayId) {
+        return nativeCanDispatchToDisplay(mPtr, deviceId, displayId);
+    }
+
     // Native callback.
     private int getKeyRepeatTimeout() {
         return ViewConfiguration.getKeyRepeatTimeout();
diff --git a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
index 22fabb2..80ab790 100644
--- a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
+++ b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
@@ -24,7 +24,7 @@
 import android.os.RemoteException;
 import android.util.Log;
 
-import com.android.internal.os.BackgroundThread;
+import com.android.server.FgThread;
 import com.android.server.ServiceWatcher;
 
 /**
@@ -84,7 +84,7 @@
                 overlaySwitchResId,
                 defaultServicePackageNameResId,
                 initialPackageNameResId,
-                BackgroundThread.getHandler()) {
+                FgThread.getHandler()) {
             @Override
             protected void onBind() {
                 runOnBinder(ActivityRecognitionProxy.this::initializeService);
diff --git a/services/core/java/com/android/server/location/GeocoderProxy.java b/services/core/java/com/android/server/location/GeocoderProxy.java
index e6f0ed9..d9602b8 100644
--- a/services/core/java/com/android/server/location/GeocoderProxy.java
+++ b/services/core/java/com/android/server/location/GeocoderProxy.java
@@ -21,7 +21,7 @@
 import android.location.GeocoderParams;
 import android.location.IGeocodeProvider;
 
-import com.android.internal.os.BackgroundThread;
+import com.android.server.FgThread;
 import com.android.server.ServiceWatcher;
 
 import java.util.List;
@@ -53,7 +53,7 @@
             int initialPackageNamesResId) {
         mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
                 defaultServicePackageNameResId, initialPackageNamesResId,
-                BackgroundThread.getHandler());
+                FgThread.getHandler());
     }
 
     private boolean bind() {
diff --git a/services/core/java/com/android/server/location/GeofenceProxy.java b/services/core/java/com/android/server/location/GeofenceProxy.java
index 38c7d49..ce93661 100644
--- a/services/core/java/com/android/server/location/GeofenceProxy.java
+++ b/services/core/java/com/android/server/location/GeofenceProxy.java
@@ -30,7 +30,7 @@
 import android.os.UserHandle;
 import android.util.Log;
 
-import com.android.internal.os.BackgroundThread;
+import com.android.server.FgThread;
 import com.android.server.ServiceWatcher;
 
 /**
@@ -82,7 +82,7 @@
         mContext = context;
         mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
                 defaultServicePackageNameResId, initialPackageNamesResId,
-                BackgroundThread.getHandler()) {
+                FgThread.getHandler()) {
             @Override
             protected void onBind() {
                 runOnBinder(mUpdateGeofenceHardware);
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 6b5b1be..776beb5 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -31,8 +31,8 @@
 import com.android.internal.location.ILocationProviderManager;
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ProviderRequest;
-import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.TransferPipe;
+import com.android.server.FgThread;
 import com.android.server.LocationManagerService;
 import com.android.server.ServiceWatcher;
 
@@ -105,7 +105,7 @@
 
         mServiceWatcher = new ServiceWatcher(context, TAG, action, overlaySwitchResId,
                 defaultServicePackageNameResId, initialPackageNamesResId,
-                BackgroundThread.getHandler()) {
+                FgThread.getHandler()) {
 
             @Override
             protected void onBind() {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 467b192..ba187c0 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -198,6 +198,7 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
@@ -2366,6 +2367,28 @@
         }
 
         @Override
+        public boolean shouldHideSilentStatusIcons(String callingPkg) {
+            checkCallerIsSameApp(callingPkg);
+
+            if (isCallerSystemOrPhone()
+                    || mListeners.isListenerPackage(callingPkg)) {
+                return mPreferencesHelper.shouldHideSilentStatusIcons();
+            } else {
+                throw new SecurityException("Only available for notification listeners");
+            }
+        }
+
+        @Override
+        public void setHideSilentStatusIcons(boolean hide) {
+            checkCallerIsSystem();
+
+            mPreferencesHelper.setHideSilentStatusIcons(hide);
+            handleSavePolicyFile();
+
+            mListeners.onStatusBarIconsBehaviorChanged(hide);
+        }
+
+        @Override
         public int getPackageImportance(String pkg) {
             checkCallerIsSystemOrSameApp(pkg);
             return mPreferencesHelper.getImportance(pkg, Binder.getCallingUid());
@@ -3633,6 +3656,22 @@
         }
 
         @Override
+        public ComponentName getAllowedNotificationAssistantForUser(int userId) {
+            checkCallerIsSystem();
+            List<ComponentName> allowedComponents = mAssistants.getAllowedComponents(userId);
+            if (allowedComponents.size() > 1) {
+                throw new IllegalStateException(
+                        "At most one NotificationAssistant: " + allowedComponents.size());
+            }
+            return CollectionUtils.firstOrNull(allowedComponents);
+        }
+
+        @Override
+        public ComponentName getAllowedNotificationAssistant() {
+            return getAllowedNotificationAssistantForUser(getCallingUserHandle().getIdentifier());
+        }
+
+        @Override
         public boolean isNotificationListenerAccessGranted(ComponentName listener) {
             Preconditions.checkNotNull(listener);
             checkCallerIsSystemOrSameApp(listener.getPackageName());
@@ -3700,8 +3739,15 @@
         @Override
         public void setNotificationAssistantAccessGrantedForUser(ComponentName assistant,
                 int userId, boolean granted) throws RemoteException {
-            Preconditions.checkNotNull(assistant);
             checkCallerIsSystemOrShell();
+            if (assistant == null) {
+                ComponentName allowedAssistant = CollectionUtils.firstOrNull(
+                        mAssistants.getAllowedComponents(userId));
+                if (allowedAssistant != null) {
+                    setNotificationAssistantAccessGrantedForUser(allowedAssistant, userId, false);
+                }
+                return;
+            }
             final long identity = Binder.clearCallingIdentity();
             try {
                 if (mAllowedManagedServicePackages.test(assistant.getPackageName())) {
@@ -7242,6 +7288,26 @@
                 }
             }
         }
+
+        @Override
+        protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
+                boolean isPrimary, boolean enabled) {
+            // Ensures that only one component is enabled at a time
+            if (enabled) {
+                List<ComponentName> allowedComponents = getAllowedComponents(userId);
+                if (!allowedComponents.isEmpty()) {
+                    ComponentName currentComponent = CollectionUtils.firstOrNull(allowedComponents);
+                    if (currentComponent.flattenToString().equals(pkgOrComponent)) return;
+                    try {
+                        getBinderService().setNotificationAssistantAccessGrantedForUser(
+                                currentComponent, userId, false);
+                    } catch (RemoteException e) {
+                        e.rethrowFromSystemServer();
+                    }
+                }
+            }
+            super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled);
+        }
     }
 
     public class NotificationListeners extends ManagedServices {
@@ -7324,6 +7390,20 @@
             return mLightTrimListeners.contains(info) ? TRIM_LIGHT : TRIM_FULL;
         }
 
+        public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+            for (final ManagedServiceInfo info : getServices()) {
+                mHandler.post(() -> {
+                    final INotificationListener listener = (INotificationListener) info.service;
+                     try {
+                        listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
+                    } catch (RemoteException ex) {
+                        Log.e(TAG, "unable to notify listener "
+                                + "(hideSilentStatusIcons): " + listener, ex);
+                    }
+                });
+            }
+        }
+
         /**
          * asynchronously notify all listeners about a new notification
          *
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 3f0043c..6ed4f5c 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -76,6 +76,7 @@
     private static final String TAG_CHANNEL = "channel";
     private static final String TAG_GROUP = "channelGroup";
     private static final String TAG_DELEGATE = "delegate";
+    private static final String TAG_STATUS_ICONS = "status_icons";
 
     private static final String ATT_VERSION = "version";
     private static final String ATT_NAME = "name";
@@ -89,10 +90,13 @@
     private static final String ATT_APP_USER_LOCKED_FIELDS = "app_user_locked_fields";
     private static final String ATT_ENABLED = "enabled";
     private static final String ATT_USER_ALLOWED = "allowed";
+    private static final String ATT_HIDE_SILENT = "hide_silent";
 
     private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
     private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
     private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
+    @VisibleForTesting
+    static final boolean DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS = false;
     private static final boolean DEFAULT_SHOW_BADGE = true;
     private static final boolean DEFAULT_ALLOW_BUBBLE = true;
     private static final boolean DEFAULT_OEM_LOCKED_IMPORTANCE  = false;
@@ -124,6 +128,7 @@
 
     private SparseBooleanArray mBadgingEnabled;
     private boolean mAreChannelsBypassingDnd;
+    private boolean mHideSilentStatusBarIcons;
 
     public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
             ZenModeHelper zenHelper) {
@@ -143,9 +148,8 @@
         String tag = parser.getName();
         if (!TAG_RANKING.equals(tag)) return;
         synchronized (mPackagePreferences) {
-            // Clobber groups and channels with the xml, but don't delete other data that wasn't present
-
-            // at the time of serialization.
+            // Clobber groups and channels with the xml, but don't delete other data that wasn't
+            // present at the time of serialization.
             mRestoredWithoutUids.clear();
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                 tag = parser.getName();
@@ -153,7 +157,10 @@
                     return;
                 }
                 if (type == XmlPullParser.START_TAG) {
-                    if (TAG_PACKAGE.equals(tag)) {
+                    if (TAG_STATUS_ICONS.equals(tag)) {
+                        mHideSilentStatusBarIcons = XmlUtils.readBooleanAttribute(
+                                parser, ATT_HIDE_SILENT, DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS);
+                    } else if (TAG_PACKAGE.equals(tag)) {
                         int uid = XmlUtils.readIntAttribute(parser, ATT_UID, UNKNOWN_UID);
                         String name = parser.getAttributeValue(null, ATT_NAME);
                         if (!TextUtils.isEmpty(name)) {
@@ -375,6 +382,11 @@
     public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
         out.startTag(null, TAG_RANKING);
         out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
+        if (mHideSilentStatusBarIcons != DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS) {
+            out.startTag(null, TAG_STATUS_ICONS);
+            out.attribute(null, ATT_HIDE_SILENT, String.valueOf(mHideSilentStatusBarIcons));
+            out.endTag(null, TAG_STATUS_ICONS);
+        }
 
         synchronized (mPackagePreferences) {
             final int N = mPackagePreferences.size();
@@ -781,6 +793,14 @@
         }
     }
 
+    public boolean shouldHideSilentStatusIcons() {
+        return mHideSilentStatusBarIcons;
+    }
+
+    public void setHideSilentStatusIcons(boolean hide) {
+        mHideSilentStatusBarIcons = hide;
+    }
+
     public void lockChannelsForOEM(String[] appOrChannelList) {
         if (appOrChannelList == null) {
             return;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index c2ac27a..62c4815 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -34,9 +34,11 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ILauncherApps;
 import android.content.pm.IOnAppsChangedListener;
+import android.content.pm.IPackageInstallerCallback;
 import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
@@ -56,6 +58,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
@@ -153,6 +156,8 @@
 
         private final Object mVouchedSignaturesLocked = new Object();
 
+        private PackageInstallerService mPackageInstallerService;
+
         public LauncherAppsImpl(Context context) {
             mContext = context;
             mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -204,8 +209,7 @@
         }
 
         /*
-         * @see android.content.pm.ILauncherApps#addOnAppsChangedListener(
-         *          android.content.pm.IOnAppsChangedListener)
+         * @see android.content.pm.ILauncherApps#addOnAppsChangedListener
          */
         @Override
         public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
@@ -228,8 +232,7 @@
         }
 
         /*
-         * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener(
-         *          android.content.pm.IOnAppsChangedListener)
+         * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener
          */
         @Override
         public void removeOnAppsChangedListener(IOnAppsChangedListener listener)
@@ -246,6 +249,44 @@
         }
 
         /**
+         * @see android.content.pm.ILauncherApps#registerPackageInstallerCallback
+         */
+        @Override
+        public void registerPackageInstallerCallback(String callingPackage,
+                IPackageInstallerCallback callback) {
+            verifyCallingPackage(callingPackage);
+            UserHandle callingIdUserHandle = new UserHandle(getCallingUserId());
+            getPackageInstallerService().registerCallback(callback, eventUserId ->
+                            isEnabledProfileOf(callingIdUserHandle,
+                                    new UserHandle(eventUserId), "shouldReceiveEvent"));
+        }
+
+        @Override
+        public ParceledListSlice<SessionInfo> getAllSessions(String callingPackage) {
+            verifyCallingPackage(callingPackage);
+            List<SessionInfo> sessionInfos = new ArrayList<>();
+            int[] userIds = mUm.getEnabledProfileIds(getCallingUserId());
+            long token = Binder.clearCallingIdentity();
+            try {
+                for (int userId : userIds) {
+                    sessionInfos.addAll(getPackageInstallerService().getAllSessions(userId)
+                            .getList());
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            return new ParceledListSlice<>(sessionInfos);
+        }
+
+        private PackageInstallerService getPackageInstallerService() {
+            if (mPackageInstallerService == null) {
+                mPackageInstallerService = ((PackageInstallerService) ((PackageManagerService)
+                        ServiceManager.getService("package")).getPackageInstaller());
+            }
+            return mPackageInstallerService;
+        }
+
+        /**
          * Register a receiver to watch for package broadcasts
          */
         private void startWatchingPackageBroadcasts() {
@@ -430,6 +471,9 @@
             if (!mVouchedSignaturesByUser.containsKey(user)) {
                 initVouchedSignatures(user);
             }
+            if (isManagedProfileAdmin(user, appInfo.packageName)) {
+                return false;
+            }
             if (mVouchProviders.contains(appInfo.packageName)) {
                 // If it's a vouching packages then we must show hidden app
                 return true;
@@ -453,6 +497,24 @@
             return true;
         }
 
+        private boolean isManagedProfileAdmin(UserHandle user, String packageName) {
+            final List<UserInfo> userInfoList = mUm.getProfiles(user.getIdentifier());
+            for (int i = 0; i < userInfoList.size(); i++) {
+                UserInfo userInfo = userInfoList.get(i);
+                if (!userInfo.isManagedProfile()) {
+                    continue;
+                }
+                ComponentName componentName = mDpm.getProfileOwnerAsUser(userInfo.getUserHandle());
+                if (componentName == null) {
+                    continue;
+                }
+                if (componentName.getPackageName().equals(packageName)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
         @VisibleForTesting
         static String computePackageCertDigest(Signature signature) {
             MessageDigest messageDigest;
@@ -848,6 +910,29 @@
         }
 
         @Override
+        public void startSessionDetailsActivityAsUser(IApplicationThread caller,
+                String callingPackage, SessionInfo sessionInfo, Rect sourceBounds,
+                Bundle opts, UserHandle userHandle) throws RemoteException {
+            int userId = userHandle.getIdentifier();
+            if (!canAccessProfile(userId, "Cannot start details activity")) {
+                return;
+            }
+
+            Intent i = new Intent(Intent.ACTION_VIEW)
+                    .setData(new Uri.Builder()
+                            .scheme("market")
+                            .authority("details")
+                            .appendQueryParameter("id", sessionInfo.appPackageName)
+                            .build())
+                    .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app")
+                            .authority(callingPackage).build());
+            i.setSourceBounds(sourceBounds);
+
+            mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage, i, opts,
+                    userId);
+        }
+
+        @Override
         public void startActivityAsUser(IApplicationThread caller, String callingPackage,
                 ComponentName component, Rect sourceBounds,
                 Bundle opts, UserHandle user) throws RemoteException {
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 60d7925..33b8641 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -51,6 +51,8 @@
 per-file UserManagerService.java = yamasani@google.com
 per-file UserRestrictionsUtils.java = omakoto@google.com
 per-file UserRestrictionsUtils.java = yamasani@google.com
+per-file UserRestrictionsUtils.java = rubinxu@google.com
+per-file UserRestrictionsUtils.java = sandness@google.com
 
 # security
 per-file KeySetHandle.java = cbrubaker@google.com
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 146a2f3..a3e0d8d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -59,7 +59,6 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SELinux;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.system.ErrnoException;
@@ -107,6 +106,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Random;
+import java.util.function.IntPredicate;
 
 /** The service responsible for installing packages. */
 public class PackageInstallerService extends IPackageInstaller.Stub implements
@@ -804,7 +804,14 @@
     public void registerCallback(IPackageInstallerCallback callback, int userId) {
         mPermissionManager.enforceCrossUserPermission(
                 Binder.getCallingUid(), userId, true, false, "registerCallback");
-        mCallbacks.register(callback, userId);
+        registerCallback(callback, eventUserId -> userId == eventUserId);
+    }
+
+    /**
+     * Assume permissions already checked and caller's identity cleared
+     */
+    public void registerCallback(IPackageInstallerCallback callback, IntPredicate userCheck) {
+        mCallbacks.register(callback, userCheck);
     }
 
     @Override
@@ -1026,8 +1033,8 @@
             super(looper);
         }
 
-        public void register(IPackageInstallerCallback callback, int userId) {
-            mCallbacks.register(callback, new UserHandle(userId));
+        public void register(IPackageInstallerCallback callback, IntPredicate userCheck) {
+            mCallbacks.register(callback, userCheck);
         }
 
         public void unregister(IPackageInstallerCallback callback) {
@@ -1040,9 +1047,8 @@
             final int n = mCallbacks.beginBroadcast();
             for (int i = 0; i < n; i++) {
                 final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i);
-                final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i);
-                // TODO: dispatch notifications for slave profiles
-                if (userId == user.getIdentifier()) {
+                final IntPredicate userCheck = (IntPredicate) mCallbacks.getBroadcastCookie(i);
+                if (userCheck.test(userId)) {
                     try {
                         invokeCallback(callback, msg);
                     } catch (RemoteException ignored) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 494ec3f..de0849f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -473,6 +473,7 @@
         final SessionInfo info = new SessionInfo();
         synchronized (mLock) {
             info.sessionId = sessionId;
+            info.userId = userId;
             info.installerPackageName = mInstallerPackageName;
             info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
                     mResolvedBaseFile.getAbsolutePath() : null;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4f20590..d0f192d 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1109,14 +1109,7 @@
 
     @Override
     public int getManagedProfileBadge(@UserIdInt int userId) {
-        int callingUserId = UserHandle.getCallingUserId();
-        if (callingUserId != userId && !hasManageUsersPermission()) {
-            if (!isSameProfileGroupNoChecks(callingUserId, userId)) {
-                throw new SecurityException(
-                        "You need MANAGE_USERS permission to: check if specified user a " +
-                        "managed profile outside your profile group");
-            }
-        }
+        checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getManagedProfileBadge");
         synchronized (mUsersLock) {
             UserInfo userInfo = getUserInfoLU(userId);
             return userInfo != null ? userInfo.profileBadge : 0;
@@ -1125,14 +1118,7 @@
 
     @Override
     public boolean isManagedProfile(int userId) {
-        int callingUserId = UserHandle.getCallingUserId();
-        if (callingUserId != userId && !hasManageUsersPermission()) {
-            if (!isSameProfileGroupNoChecks(callingUserId, userId)) {
-                throw new SecurityException(
-                        "You need MANAGE_USERS permission to: check if specified user a " +
-                        "managed profile outside your profile group");
-            }
-        }
+        checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isManagedProfile");
         synchronized (mUsersLock) {
             UserInfo userInfo = getUserInfoLU(userId);
             return userInfo != null && userInfo.isManagedProfile();
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 7ac7395..abbddf3 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -16,7 +16,7 @@
 
 package com.android.server.pm.dex;
 
-import static android.provider.DeviceConfig.FsiBoot;
+import static android.provider.DeviceConfig.DexBoot;
 
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
@@ -710,8 +710,8 @@
         return isPackageSelectedToRunOobInternal(
                 SystemProperties.getBoolean(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB, false),
                 SystemProperties.get(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST, "ALL"),
-                DeviceConfig.getProperty(FsiBoot.NAMESPACE, FsiBoot.OOB_ENABLED),
-                DeviceConfig.getProperty(FsiBoot.NAMESPACE, FsiBoot.OOB_WHITELIST),
+                DeviceConfig.getProperty(DexBoot.NAMESPACE, DexBoot.PRIV_APPS_OOB_ENABLED),
+                DeviceConfig.getProperty(DexBoot.NAMESPACE, DexBoot.PRIV_APPS_OOB_WHITELIST),
                 packageNamesInSameProcess);
     }
 
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index a2c8dac..4186154 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -24,11 +24,13 @@
 import android.os.SystemClock;
 import android.service.attention.AttentionService;
 import android.util.Slog;
+import android.util.StatsLog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * Class responsible for checking if the user is currently paying attention to the phone and
@@ -79,6 +81,11 @@
      */
     private int mWakefulness;
 
+    /**
+     * Describes how many times in a row was the timeout extended.
+     */
+    private AtomicLong mConsecutiveTimeoutExtendedCount = new AtomicLong(0);
+
     @VisibleForTesting
     final AttentionCallbackInternal mCallback = new AttentionCallbackInternal() {
 
@@ -95,6 +102,8 @@
                     }
                     if (result == AttentionService.ATTENTION_SUCCESS_PRESENT) {
                         mOnUserAttention.run();
+                    } else {
+                        resetConsecutiveExtensionCount();
                     }
                 }
             }
@@ -176,6 +185,7 @@
     public int onUserActivity(long eventTime, int event) {
         switch (event) {
             case PowerManager.USER_ACTIVITY_EVENT_ATTENTION:
+                mConsecutiveTimeoutExtendedCount.incrementAndGet();
                 return 0;
             case PowerManager.USER_ACTIVITY_EVENT_OTHER:
             case PowerManager.USER_ACTIVITY_EVENT_BUTTON:
@@ -183,6 +193,7 @@
             case PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY:
                 cancelCurrentRequestIfAny();
                 mLastUserActivityTime = eventTime;
+                resetConsecutiveExtensionCount();
                 return 1;
             default:
                 if (DEBUG) {
@@ -196,6 +207,7 @@
         mWakefulness = wakefulness;
         if (wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE) {
             cancelCurrentRequestIfAny();
+            resetConsecutiveExtensionCount();
         }
     }
 
@@ -206,6 +218,13 @@
         }
     }
 
+    private void resetConsecutiveExtensionCount() {
+        final long previousCount = mConsecutiveTimeoutExtendedCount.getAndSet(0);
+        if (previousCount > 0) {
+            StatsLog.write(StatsLog.SCREEN_TIMEOUT_EXTENSION_REPORTED, previousCount);
+        }
+    }
+
     @VisibleForTesting
     int getRequestCode() {
         return (int) (mLastUserActivityTime % Integer.MAX_VALUE);
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 03ec57b..d72270e 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -52,6 +52,7 @@
 import android.service.sms.FinancialSmsService;
 import android.telephony.IFinancialSmsCallback;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.PackageUtils;
 import android.util.Slog;
@@ -145,6 +146,9 @@
         mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
         mAppOpsManager = context.getSystemService(AppOpsManager.class);
 
+        LocalServices.addService(RoleManagerServiceInternal.class,
+                new RoleManagerServiceInternalImpl());
+
         registerUserRemovedReceiver();
     }
 
@@ -382,6 +386,19 @@
         }
     }
 
+    /**
+     * Get all roles and packages hold them.
+     *
+     * @param user The user to query to roles for
+     *
+     * @return The roles and their holders
+     */
+    @NonNull
+    private ArrayMap<String, ArraySet<String>> getRoleHoldersAsUser(@NonNull UserHandle user) {
+        RoleUserState userState = getOrCreateUserState(user.getIdentifier());
+        return userState.getRoleHolders();
+    }
+
     private class Stub extends IRoleManager.Stub {
 
         @Override
@@ -676,4 +693,16 @@
             }
         }
     }
+
+    /**
+     * Entry point for internal calls into role manager
+     */
+    private final class RoleManagerServiceInternalImpl extends RoleManagerServiceInternal {
+
+        @NonNull
+        @Override
+        public ArrayMap<String, ArraySet<String>> getRoleHoldersAsUser(@NonNull UserHandle user) {
+            return RoleManagerService.this.getRoleHoldersAsUser(user);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/role/RoleManagerServiceInternal.java b/services/core/java/com/android/server/role/RoleManagerServiceInternal.java
new file mode 100644
index 0000000..3afc3f7
--- /dev/null
+++ b/services/core/java/com/android/server/role/RoleManagerServiceInternal.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 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.role;
+
+import android.annotation.NonNull;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+/**
+ * Internal calls into {@link RoleManagerService}
+ */
+public abstract class RoleManagerServiceInternal {
+    /**
+     * Get all roles and packages hold them.
+     *
+     * @param user The user to query to roles for
+     *
+     * @return The roles and their holders
+     */
+    @NonNull
+    public abstract ArrayMap<String, ArraySet<String>> getRoleHoldersAsUser(
+            @NonNull UserHandle user);
+}
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index 02dcc49..bc68dde 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -376,7 +376,7 @@
 
             version = mVersion;
             packagesHash = mPackagesHash;
-            roles = snapshotRolesLocked();
+            roles = getRoleHolders();
         }
 
         AtomicFile atomicFile = new AtomicFile(getFile(mUserId), "roles-" + mUserId);
@@ -541,7 +541,7 @@
 
             version = mVersion;
             packagesHash = mPackagesHash;
-            roles = snapshotRolesLocked();
+            roles = getRoleHolders();
         }
 
         long fieldToken = dumpOutputStream.start(fieldName, fieldId);
@@ -570,17 +570,24 @@
         dumpOutputStream.end(fieldToken);
     }
 
-    @GuardedBy("mLock")
-    private ArrayMap<String, ArraySet<String>> snapshotRolesLocked() {
-        ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>();
-        for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) {
-            String roleName = mRoles.keyAt(i);
-            ArraySet<String> roleHolders = mRoles.valueAt(i);
+    /**
+     * Get the roles and their holders.
+     *
+     * @return A copy of the roles and their holders
+     */
+    @NonNull
+    public ArrayMap<String, ArraySet<String>> getRoleHolders() {
+        synchronized (mLock) {
+            ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>();
+            for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) {
+                String roleName = mRoles.keyAt(i);
+                ArraySet<String> roleHolders = mRoles.valueAt(i);
 
-            roleHolders = new ArraySet<>(roleHolders);
-            roles.put(roleName, roleHolders);
+                roleHolders = new ArraySet<>(roleHolders);
+                roles.put(roleName, roleHolders);
+            }
+            return roles;
         }
-        return roles;
     }
 
     /**
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index f50e776..b3cc6de 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInstaller;
+import android.content.pm.VersionedPackage;
 import android.content.rollback.PackageRollbackInfo;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
@@ -41,12 +42,10 @@
     private static final String TAG = "RollbackPackageHealthObserver";
     private static final String NAME = "rollback-observer";
     private Context mContext;
-    private RollbackManager mRollbackManager;
     private Handler mHandler;
 
     RollbackPackageHealthObserver(Context context) {
         mContext = context;
-        mRollbackManager = mContext.getSystemService(RollbackManager.class);
         HandlerThread handlerThread = new HandlerThread("RollbackPackageHealthObserver");
         handlerThread.start();
         mHandler = handlerThread.getThreadHandler();
@@ -55,7 +54,9 @@
 
     @Override
     public int onHealthCheckFailed(String packageName, long versionCode) {
-        RollbackInfo rollback = getAvailableRollback(packageName, versionCode);
+        RollbackInfo rollback =
+                getAvailableRollback(mContext.getSystemService(RollbackManager.class),
+                    packageName, versionCode);
         if (rollback == null) {
             // Don't handle the notification, no rollbacks available for the package
             return PackageHealthObserverImpact.USER_IMPACT_NONE;
@@ -66,7 +67,8 @@
 
     @Override
     public boolean execute(String packageName, long versionCode) {
-        RollbackInfo rollback = getAvailableRollback(packageName, versionCode);
+        RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
+        RollbackInfo rollback = getAvailableRollback(rollbackManager, packageName, versionCode);
         if (rollback == null) {
             // Expected a rollback to be available, what happened?
             return false;
@@ -86,12 +88,9 @@
         });
 
         // TODO(zezeozue): Log initiated metrics
-        // TODO: Pass the package as a cause package instead of using
-        // Collections.emptyList once the version of the failing package is
-        // easily available.
         mHandler.post(() ->
-                mRollbackManager.commitRollback(rollback.getRollbackId(),
-                    Collections.emptyList(),
+                rollbackManager.commitRollback(rollback.getRollbackId(),
+                    Collections.singletonList(new VersionedPackage(packageName, versionCode)),
                     rollbackReceiver.getIntentSender()));
         // Assume rollback executed successfully
         return true;
@@ -110,8 +109,9 @@
         PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs);
     }
 
-    private RollbackInfo getAvailableRollback(String packageName, long versionCode) {
-        for (RollbackInfo rollback : mRollbackManager.getAvailableRollbacks()) {
+    private RollbackInfo getAvailableRollback(RollbackManager rollbackManager,
+            String packageName, long versionCode) {
+        for (RollbackInfo rollback : rollbackManager.getAvailableRollbacks()) {
             for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
                 if (packageName.equals(packageRollback.getPackageName())
                         && packageRollback.getVersionRolledBackFrom().getVersionCode()
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index c6d2870..2be78fe3 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -23,6 +23,7 @@
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
 import static com.android.server.am.MemoryStatUtil.readRssHighWaterMarkFromProcfs;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
@@ -83,6 +84,7 @@
 import android.telephony.ModemActivityInfo;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 import android.util.StatsLog;
@@ -112,6 +114,7 @@
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
 import com.android.server.am.MemoryStatUtil.MemoryStat;
+import com.android.server.role.RoleManagerServiceInternal;
 import com.android.server.storage.DiskStatsFileLogger;
 import com.android.server.storage.DiskStatsLoggingService;
 
@@ -1781,6 +1784,60 @@
     }
 
     /**
+     * Add a RoleHolder atom for each package that holds a role.
+     *
+     * @param elapsedNanos the time since boot
+     * @param wallClockNanos the time on the clock
+     * @param pulledData the data sink to write to
+     */
+    private void pullRoleHolders(long elapsedNanos, final long wallClockNanos,
+            @NonNull List<StatsLogEventWrapper> pulledData) {
+        long callingToken = Binder.clearCallingIdentity();
+        try {
+            PackageManager pm = mContext.getPackageManager();
+            RoleManagerServiceInternal rm =
+                    LocalServices.getService(RoleManagerServiceInternal.class);
+
+            List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
+
+            int numUsers = users.size();
+            for (int userNum = 0; userNum < numUsers; userNum++) {
+                UserHandle user = users.get(userNum).getUserHandle();
+
+                ArrayMap<String, ArraySet<String>> roles = rm.getRoleHoldersAsUser(user);
+
+                int numRoles = roles.size();
+                for (int roleNum = 0; roleNum < numRoles; roleNum++) {
+                    String roleName = roles.keyAt(roleNum);
+                    ArraySet<String> holders = roles.valueAt(roleNum);
+
+                    int numHolders = holders.size();
+                    for (int holderNum = 0; holderNum < numHolders; holderNum++) {
+                        String holderName = holders.valueAt(holderNum);
+
+                        PackageInfo pkg;
+                        try {
+                            pkg = pm.getPackageInfoAsUser(holderName, 0, user.getIdentifier());
+                        } catch (PackageManager.NameNotFoundException e) {
+                            Log.w(TAG, "Role holder " + holderName + " not found");
+                            return;
+                        }
+
+                        StatsLogEventWrapper e = new StatsLogEventWrapper(StatsLog.ROLE_HOLDER,
+                                elapsedNanos, wallClockNanos);
+                        e.writeInt(pkg.applicationInfo.uid);
+                        e.writeString(holderName);
+                        e.writeString(roleName);
+                        pulledData.add(e);
+                    }
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingToken);
+        }
+    }
+
+    /**
      * Pulls various data.
      */
     @Override // Binder call
@@ -1954,6 +2011,10 @@
                 pullDebugFailingElapsedClock(tagId, elapsedNanos, wallClockNanos, ret);
                 break;
             }
+            case StatsLog.ROLE_HOLDER: {
+                pullRoleHolders(elapsedNanos, wallClockNanos, ret);
+                break;
+            }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index b0ef8a0..071dde7 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -2243,12 +2243,9 @@
         synchronized (mLock) {
             mInAmbientMode = inAmbientMode;
             final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
-            final boolean hasConnection = data != null && data.connection != null;
-            final WallpaperInfo info = hasConnection ? data.connection.mInfo : null;
-
             // The wallpaper info is null for image wallpaper, also use the engine in this case.
-            if (hasConnection && (info == null && isAodImageWallpaperEnabled()
-                    || info != null && info.supportsAmbientMode())) {
+            if (data != null && data.connection != null && (data.connection.mInfo == null
+                    || data.connection.mInfo.supportsAmbientMode())) {
                 // TODO(multi-display) Extends this method with specific display.
                 engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
             } else {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 95a6f71..d1cd1db 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -926,6 +926,10 @@
         if (callerApp != null && callerApp.hasForegroundActivities()) {
             return false;
         }
+        // don't abort if the callerApp is instrumenting with background activity starts privileges
+        if (callerApp != null && callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) {
+            return false;
+        }
         // don't abort if the callingUid is in the foreground or is a persistent system process
         final int callingUidProcState = mService.getUidStateLocked(callingUid);
         final boolean callingUidHasAnyVisibleWindow =
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 5fabde4..09ef4b9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -349,6 +349,14 @@
 
     /* Global service lock used by the package the owns this service. */
     final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
+    /**
+     * It is the same instance as {@link mGlobalLock}, just declared as a type that the
+     * locked-region-code-injection does't recognize it. It is used to skip wrapping priority
+     * booster for places that are already in the scope of another booster (e.g. computing oom-adj).
+     *
+     * @see WindowManagerThreadPriorityBooster
+     */
+    final Object mGlobalLockWithoutBoost = mGlobalLock;
     ActivityStackSupervisor mStackSupervisor;
     RootActivityContainer mRootActivityContainer;
     WindowManagerService mWindowManager;
@@ -6837,7 +6845,7 @@
 
         @Override
         public WindowProcessController getTopApp() {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 final ActivityRecord top = mRootActivityContainer.getTopResumedActivity();
                 return top != null ? top.app : null;
             }
@@ -6845,7 +6853,7 @@
 
         @Override
         public void rankTaskLayersIfNeeded() {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 if (mRootActivityContainer != null) {
                     mRootActivityContainer.rankTaskLayersIfNeeded();
                 }
@@ -6889,28 +6897,28 @@
 
         @Override
         public void onUidActive(int uid, int procState) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 mActiveUids.put(uid, procState);
             }
         }
 
         @Override
         public void onUidInactive(int uid) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 mActiveUids.remove(uid);
             }
         }
 
         @Override
         public void onActiveUidsCleared() {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 mActiveUids.clear();
             }
         }
 
         @Override
         public void onUidProcStateChanged(int uid, int procState) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 if (mActiveUids.get(uid) != null) {
                     mActiveUids.put(uid, procState);
                 }
@@ -6919,14 +6927,14 @@
 
         @Override
         public void onUidAddedToPendingTempWhitelist(int uid, String tag) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 mPendingTempWhitelist.put(uid, tag);
             }
         }
 
         @Override
         public void onUidRemovedFromPendingTempWhitelist(int uid) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 mPendingTempWhitelist.remove(uid);
             }
         }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a8492fb..080f965 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1665,35 +1665,42 @@
         final int len = devices != null ? devices.length : 0;
         for (int i = 0; i < len; i++) {
             InputDevice device = devices[i];
-            if (!device.isVirtual()) {
-                final int sources = device.getSources();
-                final int presenceFlag = device.isExternal() ?
-                        WindowManagerPolicy.PRESENCE_EXTERNAL :
-                        WindowManagerPolicy.PRESENCE_INTERNAL;
+            // Ignore virtual input device.
+            if (device.isVirtual()) {
+                continue;
+            }
 
-                // TODO(multi-display): Configure on per-display basis.
-                if (mWmService.mIsTouchDevice) {
-                    if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
-                            InputDevice.SOURCE_TOUCHSCREEN) {
-                        config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
-                    }
-                } else {
-                    config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
-                }
+            // Check if input device can dispatch events to current display.
+            // If display type is virtual, will follow the default display.
+            if (!mWmService.mInputManager.canDispatchToDisplay(device.getId(),
+                    displayInfo.type == Display.TYPE_VIRTUAL ? DEFAULT_DISPLAY : mDisplayId)) {
+                continue;
+            }
 
-                if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
-                    config.navigation = Configuration.NAVIGATION_TRACKBALL;
-                    navigationPresence |= presenceFlag;
-                } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
-                        && config.navigation == Configuration.NAVIGATION_NONAV) {
-                    config.navigation = Configuration.NAVIGATION_DPAD;
-                    navigationPresence |= presenceFlag;
-                }
+            final int sources = device.getSources();
+            final int presenceFlag = device.isExternal()
+                    ? WindowManagerPolicy.PRESENCE_EXTERNAL : WindowManagerPolicy.PRESENCE_INTERNAL;
 
-                if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
-                    config.keyboard = Configuration.KEYBOARD_QWERTY;
-                    keyboardPresence |= presenceFlag;
+            if (mWmService.mIsTouchDevice) {
+                if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) {
+                    config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
                 }
+            } else {
+                config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+            }
+
+            if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
+                config.navigation = Configuration.NAVIGATION_TRACKBALL;
+                navigationPresence |= presenceFlag;
+            } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
+                    && config.navigation == Configuration.NAVIGATION_NONAV) {
+                config.navigation = Configuration.NAVIGATION_DPAD;
+                navigationPresence |= presenceFlag;
+            }
+
+            if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
+                config.keyboard = Configuration.KEYBOARD_QWERTY;
+                keyboardPresence |= presenceFlag;
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 030cc05..8da39b6 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -138,6 +138,8 @@
     private volatile boolean mDebugging;
     // Active instrumentation running in process?
     private volatile boolean mInstrumenting;
+    // Active instrumentation with background activity starts privilege running in process?
+    private volatile boolean mInstrumentingWithBackgroundActivityStartPrivileges;
     // This process it perceptible by the user.
     private volatile boolean mPerceptible;
     // Set to true when process was launched with a wrapper attached
@@ -370,6 +372,23 @@
         return mInstrumenting;
     }
 
+    /**
+     * {@see isInstrumentingWithBackgroundActivityStartPrivileges}
+     */
+    public void setInstrumentingWithBackgroundActivityStartPrivileges(
+            boolean instrumentingWithBackgroundActivityStartPrivileges) {
+        mInstrumentingWithBackgroundActivityStartPrivileges =
+                instrumentingWithBackgroundActivityStartPrivileges;
+    }
+
+    /**
+     * @return true if the instrumentation was started by a holder of
+     * START_ACTIVITIES_FROM_BACKGROUND permission
+     */
+    boolean isInstrumentingWithBackgroundActivityStartPrivileges() {
+        return mInstrumentingWithBackgroundActivityStartPrivileges;
+    }
+
     public void setPerceptible(boolean perceptible) {
         mPerceptible = perceptible;
     }
@@ -394,13 +413,13 @@
     }
 
     public void addPackage(String packageName) {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             mPkgList.add(packageName);
         }
     }
 
     public void clearPackageList() {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             mPkgList.clear();
         }
     }
@@ -422,20 +441,18 @@
         }
     }
 
-    public void clearActivities() {
-        synchronized (mAtm.mGlobalLock) {
-            mActivities.clear();
-        }
+    void clearActivities() {
+        mActivities.clear();
     }
 
     public boolean hasActivities() {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             return !mActivities.isEmpty();
         }
     }
 
     public boolean hasVisibleActivities() {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             for (int i = mActivities.size() - 1; i >= 0; --i) {
                 final ActivityRecord r = mActivities.get(i);
                 if (r.visible) {
@@ -447,7 +464,7 @@
     }
 
     public boolean hasActivitiesOrRecentTasks() {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             return !mActivities.isEmpty() || !mRecentTasks.isEmpty();
         }
     }
@@ -462,15 +479,13 @@
         }
     }
 
-    public void finishActivities() {
-        synchronized (mAtm.mGlobalLock) {
-            ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities);
-            for (int i = 0; i < activities.size(); i++) {
-                final ActivityRecord r = activities.get(i);
-                if (!r.finishing && r.isInStackLocked()) {
-                    r.getActivityStack().finishActivityLocked(r, Activity.RESULT_CANCELED,
-                            null, "finish-heavy", true);
-                }
+    void finishActivities() {
+        ArrayList<ActivityRecord> activities = new ArrayList<>(mActivities);
+        for (int i = 0; i < activities.size(); i++) {
+            final ActivityRecord r = activities.get(i);
+            if (!r.finishing && r.isInStackLocked()) {
+                r.getActivityStack().finishActivityLocked(r, Activity.RESULT_CANCELED,
+                        null, "finish-heavy", true);
             }
         }
     }
@@ -531,15 +546,13 @@
     }
 
 
-    public void updateIntentForHeavyWeightActivity(Intent intent) {
-        synchronized (mAtm.mGlobalLock) {
-            if (mActivities.isEmpty()) {
-                return;
-            }
-            ActivityRecord hist = mActivities.get(0);
-            intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName);
-            intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTaskRecord().taskId);
+    void updateIntentForHeavyWeightActivity(Intent intent) {
+        if (mActivities.isEmpty()) {
+            return;
         }
+        ActivityRecord hist = mActivities.get(0);
+        intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName);
+        intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTaskRecord().taskId);
     }
 
     boolean shouldKillProcessForRemovedTask(TaskRecord tr) {
@@ -609,7 +622,7 @@
     }
 
     public int computeOomAdjFromActivities(int minTaskLayer, ComputeOomAdjCallback callback) {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             final int activitiesSize = mActivities.size();
             for (int j = 0; j < activitiesSize; j++) {
                 final ActivityRecord r = mActivities.get(j);
@@ -842,18 +855,16 @@
     }
 
     public boolean hasRecentTasks() {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             return !mRecentTasks.isEmpty();
         }
     }
 
-    public void clearRecentTasks() {
-        synchronized (mAtm.mGlobalLock) {
-            for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
-                mRecentTasks.get(i).clearRootProcess();
-            }
-            mRecentTasks.clear();
+    void clearRecentTasks() {
+        for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+            mRecentTasks.get(i).clearRootProcess();
         }
+        mRecentTasks.clear();
     }
 
     public void appEarlyNotResponding(String annotation, Runnable killAppCallback) {
@@ -907,19 +918,19 @@
     }
 
     public void onTopProcChanged() {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             mAtm.mVrController.onTopProcChangedLocked(this);
         }
     }
 
     public boolean isHomeProcess() {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             return this == mAtm.mHomeProcess;
         }
     }
 
     public boolean isPreviousProcess() {
-        synchronized (mAtm.mGlobalLock) {
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
             return this == mAtm.mPreviousProcess;
         }
     }
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index ff0b0d6..33317b5 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1652,6 +1652,13 @@
     im->setCustomPointerIcon(spriteIcon);
 }
 
+static jboolean nativeCanDispatchToDisplay(JNIEnv* env, jclass /* clazz */, jlong ptr,
+        jint deviceId, jint displayId) {
+
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    return im->getInputManager()->getReader()->canDispatchToDisplay(deviceId, displayId);
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gInputManagerMethods[] = {
@@ -1726,6 +1733,8 @@
             (void*) nativeReloadPointerIcons },
     { "nativeSetCustomPointerIcon", "(JLandroid/view/PointerIcon;)V",
             (void*) nativeSetCustomPointerIcon },
+    { "nativeCanDispatchToDisplay", "(JII)Z",
+            (void*) nativeCanDispatchToDisplay },
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/services/core/jni/com_android_server_security_VerityUtils.cpp b/services/core/jni/com_android_server_security_VerityUtils.cpp
index 0d888dc..988d75c 100644
--- a/services/core/jni/com_android_server_security_VerityUtils.cpp
+++ b/services/core/jni/com_android_server_security_VerityUtils.cpp
@@ -32,9 +32,67 @@
 // TODO(112037636): Always include once fsverity.h is upstreamed.
 #if __has_include(<linux/fsverity.h>)
 #include <linux/fsverity.h>
-const int kSha256Bytes = 32;
+#else
+
+// Before fs-verity is upstreamed, use the current snapshot for development.
+// https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/tree/include/uapi/linux/fsverity.h?h=fsverity
+
+#include <linux/limits.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+struct fsverity_digest {
+    __u16 digest_algorithm;
+    __u16 digest_size; /* input/output */
+    __u8 digest[];
+};
+
+#define FS_IOC_ENABLE_VERITY	_IO('f', 133)
+#define FS_IOC_MEASURE_VERITY	_IOWR('f', 134, struct fsverity_digest)
+
+#define FS_VERITY_MAGIC		"FSVerity"
+
+#define FS_VERITY_ALG_SHA256	1
+
+struct fsverity_descriptor {
+    __u8 magic[8];		/* must be FS_VERITY_MAGIC */
+    __u8 major_version;	/* must be 1 */
+    __u8 minor_version;	/* must be 0 */
+    __u8 log_data_blocksize;/* log2(data-bytes-per-hash), e.g. 12 for 4KB */
+    __u8 log_tree_blocksize;/* log2(tree-bytes-per-hash), e.g. 12 for 4KB */
+    __le16 data_algorithm;	/* hash algorithm for data blocks */
+    __le16 tree_algorithm;	/* hash algorithm for tree blocks */
+    __le32 flags;		/* flags */
+    __le32 __reserved1;	/* must be 0 */
+    __le64 orig_file_size;	/* size of the original file data */
+    __le16 auth_ext_count;	/* number of authenticated extensions */
+    __u8 __reserved2[30];	/* must be 0 */
+};
+
+#define FS_VERITY_EXT_ROOT_HASH		1
+#define FS_VERITY_EXT_PKCS7_SIGNATURE	3
+
+struct fsverity_extension {
+    __le32 length;
+    __le16 type;		/* Type of this extension (see codes above) */
+    __le16 __reserved;	/* Reserved, must be 0 */
+};
+
+struct fsverity_digest_disk {
+    __le16 digest_algorithm;
+    __le16 digest_size;
+    __u8 digest[];
+};
+
+struct fsverity_footer {
+    __le32 desc_reverse_offset;	/* distance to fsverity_descriptor */
+    __u8 magic[8];			/* FS_VERITY_MAGIC */
+} __packed;
+
 #endif
 
+const int kSha256Bytes = 32;
+
 namespace android {
 
 namespace {
@@ -73,7 +131,6 @@
 };
 
 int enableFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) {
-#if __has_include(<linux/fsverity.h>)
     const char* path = env->GetStringUTFChars(filePath, nullptr);
     ::android::base::unique_fd rfd(open(path, O_RDONLY | O_CLOEXEC));
     if (rfd.get() < 0) {
@@ -83,14 +140,9 @@
       return errno;
     }
     return 0;
-#else
-    LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
-    return ENOSYS;
-#endif
 }
 
 int measureFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) {
-#if __has_include(<linux/fsverity.h>)
     auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest) + kSha256Bytes);
     fsverity_digest* data = reinterpret_cast<fsverity_digest*>(raii->getRaw());
     data->digest_size = kSha256Bytes;  // the only input/output parameter
@@ -104,14 +156,9 @@
       return errno;
     }
     return 0;
-#else
-    LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
-    return ENOSYS;
-#endif
 }
 
 jbyteArray constructFsveritySignedData(JNIEnv* env, jobject /* clazz */, jbyteArray digest) {
-#if __has_include(<linux/fsverity.h>)
     auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest_disk) + kSha256Bytes);
     fsverity_digest_disk* data = reinterpret_cast<fsverity_digest_disk*>(raii->getRaw());
 
@@ -126,15 +173,10 @@
     memcpy(data->digest, src, kSha256Bytes);
 
     return raii->release();
-#else
-    LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
-    return 0;
-#endif
 }
 
 
 jbyteArray constructFsverityDescriptor(JNIEnv* env, jobject /* clazz */, jlong fileSize) {
-#if __has_include(<linux/fsverity.h>)
     auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_descriptor));
     fsverity_descriptor* desc = reinterpret_cast<fsverity_descriptor*>(raii->getRaw());
 
@@ -150,15 +192,10 @@
     desc->auth_ext_count = 1;
 
     return raii->release();
-#else
-    LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
-    return 0;
-#endif
 }
 
 jbyteArray constructFsverityExtension(JNIEnv* env, jobject /* clazz */, jshort extensionId,
         jint extensionDataSize) {
-#if __has_include(<linux/fsverity.h>)
     auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_extension));
     fsverity_extension* ext = reinterpret_cast<fsverity_extension*>(raii->getRaw());
 
@@ -166,15 +203,10 @@
     ext->type = extensionId;
 
     return raii->release();
-#else
-    LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
-    return 0;
-#endif
 }
 
 jbyteArray constructFsverityFooter(JNIEnv* env, jobject /* clazz */,
         jint offsetToDescriptorHead) {
-#if __has_include(<linux/fsverity.h>)
     auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_footer));
     fsverity_footer* footer = reinterpret_cast<fsverity_footer*>(raii->getRaw());
 
@@ -182,10 +214,6 @@
     memcpy(footer->magic, FS_VERITY_MAGIC, sizeof(footer->magic));
 
     return raii->release();
-#else
-    LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
-    return 0;
-#endif
 }
 
 const JNINativeMethod sMethods[] = {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 51bdbb3..a01a026 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -74,20 +74,14 @@
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
 import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
-
 import static android.provider.Telephony.Carriers.DPC_URI;
 import static android.provider.Telephony.Carriers.ENFORCE_KEY;
 import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
 
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .PROVISIONING_ENTRY_POINT_ADB;
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker
-        .STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
-
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER;
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
-
-
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -240,11 +234,11 @@
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.StatLogger;
 import com.android.internal.util.XmlUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
-import com.android.internal.util.StatLogger;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.SystemService;
 import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
@@ -7716,18 +7710,7 @@
             }
 
             // Shutting down backup manager service permanently.
-            long ident = mInjector.binderClearCallingIdentity();
-            try {
-                if (mInjector.getIBackupManager() != null) {
-                    mInjector.getIBackupManager()
-                            .setBackupServiceActive(UserHandle.USER_SYSTEM, false);
-                }
-            } catch (RemoteException e) {
-                throw new IllegalStateException("Failed deactivating backup service.", e);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
-
+            toggleBackupServiceActive(UserHandle.USER_SYSTEM, /* makeActive= */ false);
             if (isAdb()) {
                 // Log device owner provisioning was started using adb.
                 MetricsLogger.action(mContext, PROVISIONING_ENTRY_POINT_ADB, LOG_TAG_DEVICE_OWNER);
@@ -7755,7 +7738,7 @@
                 saveUserRestrictionsLocked(userId);
             }
 
-            ident = mInjector.binderClearCallingIdentity();
+            long ident = mInjector.binderClearCallingIdentity();
             try {
                 // TODO Send to system too?
                 sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED, userId);
@@ -8012,6 +7995,9 @@
                         .write();
             }
 
+            // Shutting down backup manager service permanently.
+            toggleBackupServiceActive(userHandle, /* makeActive= */ false);
+
             mOwners.setProfileOwner(who, ownerName, userHandle);
             mOwners.writeProfileOwner(userHandle);
             Slog.i(LOG_TAG, "Profile owner set: " + who + " on user " + userHandle);
@@ -8035,6 +8021,22 @@
         }
     }
 
+
+    private void toggleBackupServiceActive(int userId, boolean makeActive) {
+        long ident = mInjector.binderClearCallingIdentity();
+        try {
+            if (mInjector.getIBackupManager() != null) {
+                mInjector.getIBackupManager()
+                        .setBackupServiceActive(userId, makeActive);
+            }
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Failed deactivating backup service.", e);
+        } finally {
+            mInjector.binderRestoreCallingIdentity(ident);
+        }
+
+    }
+
     @Override
     public void clearProfileOwner(ComponentName who) {
         if (!mHasFeature) {
@@ -12787,22 +12789,9 @@
             return;
         }
         Preconditions.checkNotNull(admin);
-        synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
-        }
-
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
-            IBackupManager ibm = mInjector.getIBackupManager();
-            if (ibm != null) {
-                ibm.setBackupServiceActive(UserHandle.USER_SYSTEM, enabled);
-            }
-        } catch (RemoteException e) {
-            throw new IllegalStateException(
-                "Failed " + (enabled ? "" : "de") + "activating backup service.", e);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        enforceProfileOrDeviceOwner(admin);
+        int userId = mInjector.userHandleGetCallingUserId();
+        toggleBackupServiceActive(userId, enabled);
     }
 
     @Override
@@ -12811,11 +12800,13 @@
         if (!mHasFeature) {
             return true;
         }
+
+        enforceProfileOrDeviceOwner(admin);
         synchronized (getLockObject()) {
             try {
-                getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
                 IBackupManager ibm = mInjector.getIBackupManager();
-                return ibm != null && ibm.isBackupServiceActive(UserHandle.USER_SYSTEM);
+                return ibm != null && ibm.isBackupServiceActive(
+                    mInjector.userHandleGetCallingUserId());
             } catch (RemoteException e) {
                 throw new IllegalStateException("Failed requesting backup service state.", e);
             }
@@ -14207,7 +14198,8 @@
                         + "calendar APIs", packageName));
                 return false;
             }
-            final Intent intent = new Intent(CalendarContract.ACTION_VIEW_WORK_CALENDAR_EVENT);
+            final Intent intent = new Intent(
+                    CalendarContract.ACTION_VIEW_MANAGED_PROFILE_CALENDAR_EVENT);
             intent.setPackage(packageName);
             intent.putExtra(CalendarContract.EXTRA_EVENT_ID, eventId);
             intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, start);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
index 00a60b9..5dafe07 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
@@ -122,7 +122,7 @@
 
     private UidRecord addActiveUidRecord(int uid, long curProcStateSeq,
             long lastNetworkUpdatedProcStateSeq) {
-        final UidRecord record = new UidRecord(uid, null /* atmInternal */);
+        final UidRecord record = new UidRecord(uid);
         record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq;
         record.curProcStateSeq = curProcStateSeq;
         record.waitingForNetwork = true;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 419c736..4e21fd0c 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -250,7 +250,7 @@
     }
 
     private UidRecord addUidRecord(int uid) {
-        final UidRecord uidRec = new UidRecord(uid, null /* atmInternal */);
+        final UidRecord uidRec = new UidRecord(uid);
         uidRec.waitingForNetwork = true;
         uidRec.hasInternetPermission = true;
         mAms.mProcessList.mActiveUids.put(uid, uidRec);
@@ -405,7 +405,7 @@
 
     @Test
     public void testBlockStateForUid() {
-        final UidRecord uidRec = new UidRecord(TEST_UID, null /* atmInternal */);
+        final UidRecord uidRec = new UidRecord(TEST_UID);
         int expectedBlockState;
 
         final String errorTemplate = "Block state should be %s, prevState: %s, curState: %s";
@@ -732,7 +732,7 @@
 
     @Test
     public void testEnqueueUidChangeLocked_procStateSeqUpdated() {
-        final UidRecord uidRecord = new UidRecord(TEST_UID, null /* atmInternal */);
+        final UidRecord uidRecord = new UidRecord(TEST_UID);
         uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1;
 
         // Verify with no pending changes for TEST_UID.
@@ -778,7 +778,7 @@
     @MediumTest
     @Test
     public void testEnqueueUidChangeLocked_dispatchUidsChanged() {
-        final UidRecord uidRecord = new UidRecord(TEST_UID, null /* atmInternal */);
+        final UidRecord uidRecord = new UidRecord(TEST_UID);
         final int expectedProcState = PROCESS_STATE_SERVICE;
         uidRecord.setProcState = expectedProcState;
         uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1;
@@ -850,7 +850,7 @@
     private void verifyWaitingForNetworkStateUpdate(long curProcStateSeq,
             long lastDispatchedProcStateSeq, long lastNetworkUpdatedProcStateSeq,
             final long procStateSeqToWait, boolean expectWait) throws Exception {
-        final UidRecord record = new UidRecord(Process.myUid(), null /* atmInternal */);
+        final UidRecord record = new UidRecord(Process.myUid());
         record.curProcStateSeq = curProcStateSeq;
         record.lastDispatchedProcStateSeq = lastDispatchedProcStateSeq;
         record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq;
diff --git a/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java b/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java
index 1a231cf..2f8e545 100644
--- a/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java
@@ -18,6 +18,7 @@
 
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_ACTION_1;
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_ACTION_2;
+import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_STATSD_SAMPLE_RATE;
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_1;
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_2;
 import static android.provider.DeviceConfig.ActivityManager.KEY_COMPACT_THROTTLE_3;
@@ -61,6 +62,9 @@
 @RunWith(AndroidJUnit4.class)
 public final class AppCompactorTest {
 
+    private static final String CLEAR_DEVICE_CONFIG_KEY_CMD =
+            "device_config delete activity_manager";
+
     @Mock private AppOpsService mAppOpsService;
     private AppCompactor mCompactorUnderTest;
     private HandlerThread mHandlerThread;
@@ -70,19 +74,21 @@
     private static void clearDeviceConfig() throws IOException  {
         UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
         uiDevice.executeShellCommand(
-                "device_config delete activity_manager " + KEY_USE_COMPACTION);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + KEY_USE_COMPACTION);
         uiDevice.executeShellCommand(
-                "device_config delete activity_manager " + KEY_COMPACT_ACTION_1);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + KEY_COMPACT_ACTION_1);
         uiDevice.executeShellCommand(
-                "device_config delete activity_manager " + KEY_COMPACT_ACTION_2);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + KEY_COMPACT_ACTION_2);
         uiDevice.executeShellCommand(
-                "device_config delete activity_manager " + KEY_COMPACT_THROTTLE_1);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + KEY_COMPACT_THROTTLE_1);
         uiDevice.executeShellCommand(
-                "device_config delete activity_manager " + KEY_COMPACT_THROTTLE_2);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + KEY_COMPACT_THROTTLE_2);
         uiDevice.executeShellCommand(
-                "device_config delete activity_manager " + KEY_COMPACT_THROTTLE_3);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + KEY_COMPACT_THROTTLE_3);
         uiDevice.executeShellCommand(
-                "device_config delete activity_manager " + KEY_COMPACT_THROTTLE_4);
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + KEY_COMPACT_THROTTLE_4);
+        uiDevice.executeShellCommand(
+                CLEAR_DEVICE_CONFIG_KEY_CMD + " " + KEY_COMPACT_STATSD_SAMPLE_RATE);
     }
 
     @Before
@@ -128,6 +134,8 @@
                 is(AppCompactor.DEFAULT_COMPACT_THROTTLE_3));
         assertThat(mCompactorUnderTest.mCompactThrottleFullFull,
                 is(AppCompactor.DEFAULT_COMPACT_THROTTLE_4));
+        assertThat(mCompactorUnderTest.mStatsdSampleRate,
+                is(AppCompactor.DEFAULT_STATSD_SAMPLE_RATE));
     }
 
     @Test
@@ -155,6 +163,9 @@
         DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
                 KEY_COMPACT_THROTTLE_4,
                 Long.toString(AppCompactor.DEFAULT_COMPACT_THROTTLE_4 + 1), false);
+        DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
+                KEY_COMPACT_STATSD_SAMPLE_RATE,
+                Float.toString(AppCompactor.DEFAULT_STATSD_SAMPLE_RATE + 0.1f), false);
 
         // Then calling init will read and set that flag.
         mCompactorUnderTest.init();
@@ -173,6 +184,8 @@
                 is(AppCompactor.DEFAULT_COMPACT_THROTTLE_3 + 1));
         assertThat(mCompactorUnderTest.mCompactThrottleFullFull,
                 is(AppCompactor.DEFAULT_COMPACT_THROTTLE_4 + 1));
+        assertThat(mCompactorUnderTest.mStatsdSampleRate,
+                is(AppCompactor.DEFAULT_STATSD_SAMPLE_RATE + 0.1f));
     }
 
     @Test
@@ -365,6 +378,63 @@
                 is(AppCompactor.DEFAULT_COMPACT_THROTTLE_4));
     }
 
+    @Test
+    public void statsdSampleRate_listensToDeviceConfigChanges() throws InterruptedException {
+        mCompactorUnderTest.init();
+
+        // When we override mStatsdSampleRate with a reasonable values ...
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
+                KEY_COMPACT_STATSD_SAMPLE_RATE,
+                Float.toString(AppCompactor.DEFAULT_STATSD_SAMPLE_RATE + 0.1f), false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS), is(true));
+
+        // Then that override is reflected in the compactor.
+        assertThat(mCompactorUnderTest.mStatsdSampleRate,
+                is(AppCompactor.DEFAULT_STATSD_SAMPLE_RATE + 0.1f));
+    }
+
+    @Test
+    public void statsdSanokeRate_listensToDeviceConfigChangesBadValues()
+            throws InterruptedException {
+        mCompactorUnderTest.init();
+
+        // When we override mStatsdSampleRate with a reasonable values ...
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
+                KEY_COMPACT_STATSD_SAMPLE_RATE, "foo", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS), is(true));
+
+        // Then that override is reflected in the compactor.
+        assertThat(mCompactorUnderTest.mStatsdSampleRate,
+                is(AppCompactor.DEFAULT_STATSD_SAMPLE_RATE));
+    }
+
+    @Test
+    public void statsdSanokeRate_listensToDeviceConfigChangesOutOfRangeValues()
+            throws InterruptedException {
+        mCompactorUnderTest.init();
+
+        // When we override mStatsdSampleRate with an value outside of [0..1]...
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
+                KEY_COMPACT_STATSD_SAMPLE_RATE,
+                Float.toString(-1.0f), false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS), is(true));
+
+        // Then the values is capped in the range.
+        assertThat(mCompactorUnderTest.mStatsdSampleRate, is(0.0f));
+
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
+                KEY_COMPACT_STATSD_SAMPLE_RATE,
+                Float.toString(1.01f), false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS), is(true));
+
+        // Then the values is capped in the range.
+        assertThat(mCompactorUnderTest.mStatsdSampleRate, is(1.0f));
+    }
+
     private class TestInjector extends Injector {
         @Override
         public AppOpsService getAppOpsService(File file, Handler handler) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
index 1de1e4e..0b488c0 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.INotificationManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.IPackageManager;
@@ -36,22 +37,17 @@
 import android.util.IntArray;
 import android.util.Xml;
 
-import com.android.internal.util.FastXmlSerializer;
 import com.android.server.UiServiceTestCase;
 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
 
 import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -65,6 +61,8 @@
     private UserManager mUm;
     @Mock
     NotificationManagerService mNm;
+    @Mock
+    private INotificationManager mINm;
 
     NotificationAssistants mAssistants;
 
@@ -83,6 +81,7 @@
         getContext().setMockPackageManager(mPm);
         getContext().addMockSystemService(Context.USER_SERVICE, mUm);
         mAssistants = spy(mNm.new NotificationAssistants(getContext(), mLock, mUserProfiles, miPm));
+        when(mNm.getBinderService()).thenReturn(mINm);
 
         List<ResolveInfo> approved = new ArrayList<>();
         ResolveInfo resolve = new ResolveInfo();
@@ -136,4 +135,30 @@
         verify(mAssistants, times(1)).addApprovedList(
                 new ComponentName("b", "b").flattenToString(),10, true);
     }
+
+    @Test
+    public void testSetPackageOrComponentEnabled_onlyOnePackage() throws Exception {
+        ComponentName component1 = ComponentName.unflattenFromString("package/Component1");
+        ComponentName component2 = ComponentName.unflattenFromString("package/Component2");
+        mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true,
+                true);
+        verify(mINm, never()).setNotificationAssistantAccessGrantedForUser(any(ComponentName.class),
+                eq(mZero.id), anyBoolean());
+
+        mAssistants.setPackageOrComponentEnabled(component2.flattenToString(), mZero.id, true,
+                true);
+        verify(mINm, times(1)).setNotificationAssistantAccessGrantedForUser(component1, mZero.id,
+                false);
+    }
+
+    @Test
+    public void testSetPackageOrComponentEnabled_samePackage() throws Exception {
+        ComponentName component1 = ComponentName.unflattenFromString("package/Component1");
+        mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true,
+                true);
+        mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true,
+                true);
+        verify(mINm, never()).setNotificationAssistantAccessGrantedForUser(any(ComponentName.class),
+                eq(mZero.id), anyBoolean());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 5d46f0f..4cae3b3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2029,6 +2029,31 @@
     }
 
     @Test
+    public void testGetAssistantAllowedForUser() throws Exception {
+        UserHandle user = UserHandle.of(10);
+        try {
+            mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
+        } catch (IllegalStateException e) {
+            if (!e.getMessage().contains("At most one NotificationAssistant")) {
+                throw e;
+            }
+        }
+        verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
+    }
+
+    @Test
+    public void testGetAssistantAllowed() throws Exception {
+        try {
+            mBinderService.getAllowedNotificationAssistant();
+        } catch (IllegalStateException e) {
+            if (!e.getMessage().contains("At most one NotificationAssistant")) {
+                throw e;
+            }
+        }
+        verify(mAssistants, times(1)).getAllowedComponents(0);
+    }
+
+    @Test
     public void testSetDndAccessForUser() throws Exception {
         UserHandle user = UserHandle.of(10);
         ComponentName c = ComponentName.unflattenFromString("package/Component");
@@ -2089,6 +2114,54 @@
     }
 
     @Test
+    public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
+        ArrayList<ComponentName> componentList = new ArrayList<>();
+        ComponentName c = ComponentName.unflattenFromString("package/Component");
+        componentList.add(c);
+        when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
+
+        try {
+            mBinderService.setNotificationAssistantAccessGranted(null, true);
+        } catch (SecurityException e) {
+            if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
+                throw e;
+            }
+        }
+
+        verify(mAssistants, times(1)).setPackageOrComponentEnabled(
+                c.flattenToString(), 0, true, false);
+        verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
+                c.flattenToString(), 0, false,  false);
+        verify(mListeners, never()).setPackageOrComponentEnabled(
+                any(), anyInt(), anyBoolean(), anyBoolean());
+    }
+
+    @Test
+    public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
+        UserHandle user = UserHandle.of(10);
+        ArrayList<ComponentName> componentList = new ArrayList<>();
+        ComponentName c = ComponentName.unflattenFromString("package/Component");
+        componentList.add(c);
+        when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
+
+        try {
+            mBinderService.setNotificationAssistantAccessGrantedForUser(
+                    null, user.getIdentifier(), true);
+        } catch (SecurityException e) {
+            if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
+                throw e;
+            }
+        }
+
+        verify(mAssistants, times(1)).setPackageOrComponentEnabled(
+                c.flattenToString(), user.getIdentifier(), true, false);
+        verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
+                c.flattenToString(), user.getIdentifier(), false,  false);
+        verify(mListeners, never()).setPackageOrComponentEnabled(
+                any(), anyInt(), anyBoolean(), anyBoolean());
+    }
+
+    @Test
     public void testSetDndAccess() throws Exception {
         ComponentName c = ComponentName.unflattenFromString("package/Component");
         try {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index bde9dde..47ec390 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -2006,6 +2006,28 @@
     }
 
     @Test
+    public void testXml_statusBarIcons_default() throws Exception {
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        loadStreamXml(baos, false);
+
+        assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
+                mHelper.shouldHideSilentStatusIcons());
+    }
+
+    @Test
+    public void testXml_statusBarIcons() throws Exception {
+        mHelper.setHideSilentStatusIcons(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        loadStreamXml(baos, false);
+
+        assertEquals(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
+                mHelper.shouldHideSilentStatusIcons());
+    }
+
+    @Test
     public void testSetNotificationDelegate() {
         mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
         assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index ace965b..62ec838 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -561,7 +561,7 @@
         runAndVerifyBackgroundActivityStartsSubtest("allowed_noStartsAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
     }
 
     /**
@@ -576,7 +576,7 @@
                 "disallowed_unsupportedUsecase_aborted", true,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
     }
 
     /**
@@ -591,57 +591,64 @@
         runAndVerifyBackgroundActivityStartsSubtest("disallowed_rootUid_notAborted", false,
                 Process.ROOT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest("disallowed_systemUid_notAborted", false,
                 Process.SYSTEM_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest("disallowed_nfcUid_notAborted", false,
                 Process.NFC_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callingUidHasVisibleWindow_notAborted", false,
                 UNIMPORTANT_UID, true, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callingUidProcessStateTop_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_realCallingUidHasVisibleWindow_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, true, PROCESS_STATE_TOP + 1,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_realCallingUidProcessStateTop_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP,
-                false, false, false);
+                false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_hasForegroundActivities_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                true, false, false);
+                true, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callerIsRecents_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, true, false);
+                false, true, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callerIsWhitelisted_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, true);
+                false, false, true, false);
+        runAndVerifyBackgroundActivityStartsSubtest(
+                "disallowed_callerIsInstrumentingWithBackgroundActivityStartPrivileges_notAborted",
+                false,
+                UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+                UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+                false, false, false, true);
     }
 
     private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
             int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState,
             int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState,
             boolean hasForegroundActivities, boolean callerIsRecents,
-            boolean callerIsTempWhitelisted) {
+            boolean callerIsTempWhitelisted,
+            boolean callerIsInstrumentingWithBackgroundActivityStartPrivileges) {
         // window visibility
         doReturn(callingUidHasVisibleWindow).when(mService.mWindowManager.mRoot)
                 .isAnyNonToastWindowVisibleForUid(callingUid);
@@ -664,6 +671,9 @@
         doReturn(callerIsRecents).when(recentTasks).isCallerRecents(callingUid);
         // caller is temp whitelisted
         callerApp.setAllowBackgroundActivityStarts(callerIsTempWhitelisted);
+        // caller is instrumenting with background activity starts privileges
+        callerApp.setInstrumentingWithBackgroundActivityStartPrivileges(
+                callerIsInstrumentingWithBackgroundActivityStartPrivileges);
 
         final ActivityOptions options = spy(ActivityOptions.makeBasic());
         ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
index 9a30b35..22fc159 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
@@ -50,8 +50,8 @@
     public static final String TAG = "IorapForwardingService";
     /** $> adb shell 'setprop log.tag.IorapdForwardingService VERBOSE' */
     public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    /** $> adb shell 'setprop iorapd.enable true' */
-    private static boolean IS_ENABLED = SystemProperties.getBoolean("iorapd.enable", true);
+    /** $> adb shell 'setprop ro.iorapd.enable true' */
+    private static boolean IS_ENABLED = SystemProperties.getBoolean("ro.iorapd.enable", true);
     /** $> adb shell 'setprop iorapd.forwarding_service.wtf_crash true' */
     private static boolean WTF_CRASH = SystemProperties.getBoolean(
             "iorapd.forwarding_service.wtf_crash", false);
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index 4bca404..6c45cc4 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
@@ -112,13 +113,13 @@
                     mSlotId, 0, null).sendToTarget();
         }
 
-        private void registerForStateChanged(INetworkServiceCallback callback) {
+        private void registerForStateChanged(@NonNull INetworkServiceCallback callback) {
             synchronized (mNetworkRegistrationStateChangedCallbacks) {
                 mNetworkRegistrationStateChangedCallbacks.add(callback);
             }
         }
 
-        private void unregisterForStateChanged(INetworkServiceCallback callback) {
+        private void unregisterForStateChanged(@NonNull INetworkServiceCallback callback) {
             synchronized (mNetworkRegistrationStateChangedCallbacks) {
                 mNetworkRegistrationStateChangedCallbacks.remove(callback);
             }
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index 0d94c4d..c1786be 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -17,12 +17,15 @@
 package android.telephony;
 
 import android.annotation.UnsupportedAppUsage;
+import android.hardware.radio.V1_0.RadioTechnology;
+import android.hardware.radio.V1_4.CellInfo.Info;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import com.android.internal.telephony.RILConstants;
 
+
 /**
  * Object to indicate the phone radio type and access technology.
  *
@@ -33,32 +36,34 @@
     /**
      * TODO: get rid of RAF definition in RadioAccessFamily and
      * use {@link TelephonyManager.NetworkTypeBitMask}
+     * TODO: public definition {@link TelephonyManager.NetworkTypeBitMask} is long.
+     * TODO: Convert from int to long everywhere including HAL definitions.
      */
     // 2G
-    public static final int RAF_UNKNOWN = TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN;
-    public static final int RAF_GSM = TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
-    public static final int RAF_GPRS = TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
-    public static final int RAF_EDGE = TelephonyManager.NETWORK_TYPE_BITMASK_EDGE;
-    public static final int RAF_IS95A = TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
-    public static final int RAF_IS95B = TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
-    public static final int RAF_1xRTT = TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
+    public static final int RAF_UNKNOWN = (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN;
+    public static final int RAF_GSM = (int) TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
+    public static final int RAF_GPRS = (int) TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
+    public static final int RAF_EDGE = (int) TelephonyManager.NETWORK_TYPE_BITMASK_EDGE;
+    public static final int RAF_IS95A = (int) TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
+    public static final int RAF_IS95B = (int) TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
+    public static final int RAF_1xRTT = (int) TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
     // 3G
-    public static final int RAF_EVDO_0 = TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0;
-    public static final int RAF_EVDO_A = TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A;
-    public static final int RAF_EVDO_B = TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B;
-    public static final int RAF_EHRPD = TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD;
-    public static final int RAF_HSUPA = TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA;
-    public static final int RAF_HSDPA = TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA;
-    public static final int RAF_HSPA = TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;
-    public static final int RAF_HSPAP = TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP;
-    public static final int RAF_UMTS = TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
-    public static final int RAF_TD_SCDMA = TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA;
+    public static final int RAF_EVDO_0 = (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0;
+    public static final int RAF_EVDO_A = (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A;
+    public static final int RAF_EVDO_B = (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B;
+    public static final int RAF_EHRPD = (int) TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD;
+    public static final int RAF_HSUPA = (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA;
+    public static final int RAF_HSDPA = (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA;
+    public static final int RAF_HSPA = (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;
+    public static final int RAF_HSPAP = (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP;
+    public static final int RAF_UMTS = (int) TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
+    public static final int RAF_TD_SCDMA = (int) TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA;
     // 4G
-    public static final int RAF_LTE = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
-    public static final int RAF_LTE_CA = TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
+    public static final int RAF_LTE = (int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
+    public static final int RAF_LTE_CA = (int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
 
     // 5G
-    public static final int RAF_NR = TelephonyManager.NETWORK_TYPE_BITMASK_NR;
+    public static final int RAF_NR = (int) TelephonyManager.NETWORK_TYPE_BITMASK_NR;
 
     // Grouping of RAFs
     // 2G
@@ -147,20 +152,20 @@
     /**
      * Implement the Parcelable interface.
      */
-    public static final Creator<RadioAccessFamily> CREATOR =
-            new Creator<RadioAccessFamily>() {
+    public static final Creator<android.telephony.RadioAccessFamily> CREATOR =
+            new Creator<android.telephony.RadioAccessFamily>() {
 
         @Override
-        public RadioAccessFamily createFromParcel(Parcel in) {
+        public android.telephony.RadioAccessFamily createFromParcel(Parcel in) {
             int phoneId = in.readInt();
             int radioAccessFamily = in.readInt();
 
-            return new RadioAccessFamily(phoneId, radioAccessFamily);
+            return new android.telephony.RadioAccessFamily(phoneId, radioAccessFamily);
         }
 
         @Override
-        public RadioAccessFamily[] newArray(int size) {
-            return new RadioAccessFamily[size];
+        public android.telephony.RadioAccessFamily[] newArray(int size) {
+            return new android.telephony.RadioAccessFamily[size];
         }
     };
 
@@ -391,76 +396,78 @@
     }
 
     /**
-     * convert RAF from {@link ServiceState.RilRadioTechnology} bitmask to
+     * convert RAF from {@link android.hardware.radio.V1_0.RadioAccessFamily} to
      * {@link TelephonyManager.NetworkTypeBitMask}, the bitmask represented by
-     * {@link TelephonyManager.NetworkType}. Reasons are {@link TelephonyManager.NetworkType} are
-     * public while {@link ServiceState.RilRadioTechnology} are hidden. We
-     * don't want to expose two sets of definition to public.
+     * {@link TelephonyManager.NetworkType}.
      *
-     * @param raf bitmask represented by {@link ServiceState.RilRadioTechnology}
+     * @param raf {@link android.hardware.radio.V1_0.RadioAccessFamily}
      * @return {@link TelephonyManager.NetworkTypeBitMask}
      */
     public static int convertToNetworkTypeBitMask(int raf) {
         int networkTypeRaf = 0;
 
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GSM)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.GSM) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GPRS)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.GPRS) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EDGE)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EDGE) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EDGE;
         }
         // convert both IS95A/IS95B to CDMA as network mode doesn't support CDMA
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IS95A)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.IS95A) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IS95B)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.IS95B) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.ONE_X_RTT) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EVDO_0) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EVDO_A) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EVDO_B) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EHRPD) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSUPA) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSDPA) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPA)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSPA) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSPAP) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_UMTS)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.UMTS) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.TD_SCDMA) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.LTE) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA)) != 0) {
+        if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.LTE_CA) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
         }
-        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_NR)) != 0) {
+        if ((raf & android.hardware.radio.V1_4.RadioAccessFamily.NR) != 0) {
             networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_NR;
         }
+        // TODO: need hal definition
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN;
+        }
 
         return (networkTypeRaf == 0) ? TelephonyManager.NETWORK_TYPE_UNKNOWN : networkTypeRaf;
     }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 869cf1c..dfe36ef 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2577,8 +2577,14 @@
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setPreferredDataSubscriptionId(int subId) {
         if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
-        setSubscriptionPropertyHelper(DEFAULT_SUBSCRIPTION_ID, "setPreferredDataSubscriptionId",
-                (iSub)-> iSub.setPreferredDataSubscriptionId(subId));
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                iSub.setPreferredDataSubscriptionId(subId);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d163556..a1fb090 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,6 +23,7 @@
 import android.Manifest;
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
+import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -71,6 +72,7 @@
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 
 import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.annotations.VisibleForTesting;
@@ -3263,6 +3265,35 @@
         }
     }
 
+    /**
+     * Get the mapping from logical slots to physical slots. The mapping represent by a pair list.
+     * The key of the piar is the logical slot id and the value of the pair is the physical
+     * slots id mapped to this logical slot id.
+     *
+     * @return an pair list indicates the mapping from logical slots to physical slots. The size of
+     * the list should be {@link #getPhoneCount()} if success, otherwise return an empty list.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @NonNull
+    public List<Pair<Integer, Integer>> getLogicalToPhysicalSlotMapping() {
+        List<Pair<Integer, Integer>> slotMapping = new ArrayList<>();
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                int[] slotMappingArray = telephony.getSlotsMapping();
+                for (int i = 0; i < slotMappingArray.length; i++) {
+                    slotMapping.add(new Pair(i, slotMappingArray[i]));
+                }
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "getSlotsMapping RemoteException", e);
+        }
+        return slotMapping;
+    }
+
     //
     //
     // Subscriber Info
@@ -6528,17 +6559,17 @@
      * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
      * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
-     * @return a 32-bit bitmap.
+     * @return The bitmap of preferred network types.
      *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     @SystemApi
-    public @NetworkTypeBitMask int getPreferredNetworkTypeBitmap() {
+    public @NetworkTypeBitMask long getPreferredNetworkTypeBitmap() {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return RadioAccessFamily.getRafFromNetworkType(
+                return (long) RadioAccessFamily.getRafFromNetworkType(
                         telephony.getPreferredNetworkType(getSubId()));
             }
         } catch (RemoteException ex) {
@@ -6773,18 +6804,19 @@
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
      * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
-     * @param networkTypeBitmap a 32-bit bitmap.
+     * @param networkTypeBitmap The bitmap of preferred network types.
      * @return true on success; false on any failure.
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     @SystemApi
-    public boolean setPreferredNetworkTypeBitmap(@NetworkTypeBitMask int networkTypeBitmap) {
+    public boolean setPreferredNetworkTypeBitmap(@NetworkTypeBitMask long networkTypeBitmap) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 return telephony.setPreferredNetworkType(
-                        getSubId(), RadioAccessFamily.getNetworkTypeFromRaf(networkTypeBitmap));
+                        getSubId(), RadioAccessFamily.getNetworkTypeFromRaf(
+                                (int) networkTypeBitmap));
             }
         } catch (RemoteException ex) {
             Rlog.e(TAG, "setPreferredNetworkType RemoteException", ex);
@@ -9693,7 +9725,7 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, prefix = {"NETWORK_TYPE_BITMASK_"},
+    @LongDef(flag = true, prefix = {"NETWORK_TYPE_BITMASK_"},
             value = {NETWORK_TYPE_BITMASK_UNKNOWN,
                     NETWORK_TYPE_BITMASK_GSM,
                     NETWORK_TYPE_BITMASK_GPRS,
@@ -9722,118 +9754,125 @@
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_UNKNOWN = (1 << NETWORK_TYPE_UNKNOWN);
+    public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L;
     /**
      * network type bitmask indicating the support of radio tech GSM.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_GSM = (1 << NETWORK_TYPE_GSM);
+    public static final long NETWORK_TYPE_BITMASK_GSM = (1 << (NETWORK_TYPE_GSM -1));
     /**
      * network type bitmask indicating the support of radio tech GPRS.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_GPRS = (1 << NETWORK_TYPE_GPRS);
+    public static final long NETWORK_TYPE_BITMASK_GPRS = (1 << (NETWORK_TYPE_GPRS -1));
     /**
      * network type bitmask indicating the support of radio tech EDGE.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_EDGE = (1 << NETWORK_TYPE_EDGE);
+    public static final long NETWORK_TYPE_BITMASK_EDGE = (1 << (NETWORK_TYPE_EDGE -1));
     /**
      * network type bitmask indicating the support of radio tech CDMA(IS95A/IS95B).
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_CDMA = (1 << NETWORK_TYPE_CDMA);
+    public static final long NETWORK_TYPE_BITMASK_CDMA = (1 << (NETWORK_TYPE_CDMA -1));
     /**
      * network type bitmask indicating the support of radio tech 1xRTT.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_1xRTT = (1 << NETWORK_TYPE_1xRTT);
+    public static final long NETWORK_TYPE_BITMASK_1xRTT = (1 << (NETWORK_TYPE_1xRTT - 1));
     // 3G
     /**
      * network type bitmask indicating the support of radio tech EVDO 0.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_EVDO_0 = (1 << NETWORK_TYPE_EVDO_0);
+    public static final long NETWORK_TYPE_BITMASK_EVDO_0 = (1 << (NETWORK_TYPE_EVDO_0 -1));
     /**
      * network type bitmask indicating the support of radio tech EVDO A.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_EVDO_A = (1 << NETWORK_TYPE_EVDO_A);
+    public static final long NETWORK_TYPE_BITMASK_EVDO_A = (1 << (NETWORK_TYPE_EVDO_A - 1));
     /**
      * network type bitmask indicating the support of radio tech EVDO B.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_EVDO_B = (1 << NETWORK_TYPE_EVDO_B);
+    public static final long NETWORK_TYPE_BITMASK_EVDO_B = (1 << (NETWORK_TYPE_EVDO_B -1));
     /**
      * network type bitmask indicating the support of radio tech EHRPD.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_EHRPD = (1 << NETWORK_TYPE_EHRPD);
+    public static final long NETWORK_TYPE_BITMASK_EHRPD = (1 << (NETWORK_TYPE_EHRPD -1));
     /**
      * network type bitmask indicating the support of radio tech HSUPA.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_HSUPA = (1 << NETWORK_TYPE_HSUPA);
+    public static final long NETWORK_TYPE_BITMASK_HSUPA = (1 << (NETWORK_TYPE_HSUPA -1));
     /**
      * network type bitmask indicating the support of radio tech HSDPA.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_HSDPA = (1 << NETWORK_TYPE_HSDPA);
+    public static final long NETWORK_TYPE_BITMASK_HSDPA = (1 << (NETWORK_TYPE_HSDPA -1));
     /**
      * network type bitmask indicating the support of radio tech HSPA.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_HSPA = (1 << NETWORK_TYPE_HSPA);
+    public static final long NETWORK_TYPE_BITMASK_HSPA = (1 << (NETWORK_TYPE_HSPA -1));
     /**
      * network type bitmask indicating the support of radio tech HSPAP.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_HSPAP = (1 << NETWORK_TYPE_HSPAP);
+    public static final long NETWORK_TYPE_BITMASK_HSPAP = (1 << (NETWORK_TYPE_HSPAP -1));
     /**
      * network type bitmask indicating the support of radio tech UMTS.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_UMTS = (1 << NETWORK_TYPE_UMTS);
+    public static final long NETWORK_TYPE_BITMASK_UMTS = (1 << (NETWORK_TYPE_UMTS -1));
     /**
      * network type bitmask indicating the support of radio tech TD_SCDMA.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_TD_SCDMA = (1 << NETWORK_TYPE_TD_SCDMA);
+    public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = (1 << (NETWORK_TYPE_TD_SCDMA -1));
     // 4G
     /**
      * network type bitmask indicating the support of radio tech LTE.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_LTE = (1 << NETWORK_TYPE_LTE);
+    public static final long NETWORK_TYPE_BITMASK_LTE = (1 << (NETWORK_TYPE_LTE -1));
     /**
      * network type bitmask indicating the support of radio tech LTE CA (carrier aggregation).
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_LTE_CA = (1 << NETWORK_TYPE_LTE_CA);
+    public static final long NETWORK_TYPE_BITMASK_LTE_CA = (1 << (NETWORK_TYPE_LTE_CA -1));
 
     /**
      * network type bitmask indicating the support of radio tech NR(New Radio) 5G.
      * @hide
      */
     @SystemApi
-    public static final int NETWORK_TYPE_BITMASK_NR = (1 << NETWORK_TYPE_NR);
+    public static final long NETWORK_TYPE_BITMASK_NR = (1 << (NETWORK_TYPE_NR -1));
+
+    /**
+     * network type bitmask indicating the support of radio tech IWLAN.
+     * @hide
+     */
+    @SystemApi
+    public static final long NETWORK_TYPE_BITMASK_IWLAN = (1 << (NETWORK_TYPE_IWLAN -1));
 
     /**
      * @return Modem supported radio access family bitmask
@@ -9844,11 +9883,11 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public @NetworkTypeBitMask int getSupportedRadioAccessFamily() {
+    public @NetworkTypeBitMask long getSupportedRadioAccessFamily() {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.getRadioAccessFamily(getSlotIndex(), getOpPackageName());
+                return (long) telephony.getRadioAccessFamily(getSlotIndex(), getOpPackageName());
             } else {
                 // This can happen when the ITelephony interface is not up yet.
                 return NETWORK_TYPE_BITMASK_UNKNOWN;
@@ -10230,4 +10269,24 @@
             Rlog.e(TAG, "switchMultiSimConfig RemoteException", ex);
         }
     }
+
+    /**
+     * Get whether reboot is required or not after making changes to modem configurations.
+     * @Return {@code True} if reboot is required after making changes to modem configurations,
+     * otherwise return {@code False}.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public boolean isRebootRequiredForModemConfigChange() {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.isRebootRequiredForModemConfigChange();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "isRebootRequiredForModemConfigChange RemoteException", e);
+        }
+        return false;
+    }
 }
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 74d1e83..79572b9 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -157,7 +157,10 @@
                                   @Nullable LinkProperties linkProperties,
                                   @Nullable DataServiceCallback callback) {
             // The default implementation is to return unsupported.
-            callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
+            if (callback != null) {
+                callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED,
+                        null);
+            }
         }
 
         /**
@@ -176,7 +179,9 @@
         public void deactivateDataCall(int cid, @DeactivateDataReason int reason,
                                        @Nullable DataServiceCallback callback) {
             // The default implementation is to return unsupported.
-            callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            if (callback != null) {
+                callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            }
         }
 
         /**
@@ -190,7 +195,10 @@
         public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
                                         @Nullable DataServiceCallback callback) {
             // The default implementation is to return unsupported.
-            callback.onSetInitialAttachApnComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            if (callback != null) {
+                callback.onSetInitialAttachApnComplete(
+                        DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            }
         }
 
         /**
@@ -206,7 +214,9 @@
         public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
                                    @Nullable DataServiceCallback callback) {
             // The default implementation is to return unsupported.
-            callback.onSetDataProfileComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            if (callback != null) {
+                callback.onSetDataProfileComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            }
         }
 
         /**
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index bca088e..b2f5802 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -464,7 +464,7 @@
             return null;
         }
         try {
-            return getIEuiccController().getEid(mCardId);
+            return getIEuiccController().getEid(mCardId, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -502,6 +502,15 @@
      * Without the former, an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be
      * returned in the callback intent to prompt the user to accept the download.
      *
+     * <p>On a multi-active SIM device, requires the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
+     * only if the targeted eUICC does not currently have an active subscription or the calling app
+     * is authorized to manage the active subscription on the target eUICC, and the calling app is
+     * authorized to manage any active subscription on any SIM. Without it, an
+     * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
+     * intent to prompt the user to accept the download. The caller should also be authorized to
+     * manage the subscription to be downloaded.
+     *
      * @param subscription the subscription to download.
      * @param switchAfterDownload if true, the profile will be activated upon successful download.
      * @param callbackIntent a PendingIntent to launch when the operation completes.
@@ -704,9 +713,21 @@
      * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
      * intent to prompt the user to accept the download.
      *
+     * <p>On a multi-active SIM device, requires the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
+     *  only if the targeted eUICC does not currently have an active subscription or the calling app
+     * is authorized to manage the active subscription on the target eUICC, and the calling app is
+     * authorized to manage any active subscription on any SIM. Without it, an
+     * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
+     * intent to prompt the user to accept the download. The caller should also be authorized to
+     * manage the subscription to be enabled.
+     *
      * @param subscriptionId the ID of the subscription to enable. May be
      *     {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
-     *     current profile without activating another profile to replace it.
+     *     current profile without activating another profile to replace it. If it's a disable
+     *     operation, requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS}
+     *     permission, or the calling app must be authorized to manage the active subscription on
+     *     the target eUICC.
      * @param callbackIntent a PendingIntent to launch when the operation completes.
      */
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index a49d2d9..6ce9de4 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -220,7 +220,7 @@
      * @hide
      *
      */
-    int setPreferredDataSubscriptionId(int subId);
+    void setPreferredDataSubscriptionId(int subId);
 
     /**
      * Get which subscription is preferred for cellular data.
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 927c676..762d886 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1848,4 +1848,14 @@
      * @hide
      */
     int getNumOfActiveSims();
+
+    /**
+     * Get if reboot is required upon altering modems configurations
+     */
+    boolean isRebootRequiredForModemConfigChange();
+
+    /**
+     * Get the mapping from logical slots to physical slots.
+     */
+    int[] getSlotsMapping();
 }
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 6567ea7..603c4c2 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -194,6 +194,13 @@
      */
     static final String PROPERTY_MULTI_SIM_CONFIG = "persist.radio.multisim.config";
 
+     /**
+     * Property to indicate if reboot is required when changing modems configurations
+     * Type:  String(true, false) default is false; most devices don't need reboot
+     */
+    String PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE =
+             "persist.radio.reboot_on_modem_change";
+
     /**
      * Property to store default subscription.
      */
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 14a36c8..2016915 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -31,7 +31,7 @@
         String callingPackage, in PendingIntent callbackIntent);
     oneway void getDefaultDownloadableSubscriptionList(int cardId,
         String callingPackage, in PendingIntent callbackIntent);
-    String getEid(int cardId);
+    String getEid(int cardId, String callingPackage);
     int getOtaStatus(int cardId);
     oneway void downloadSubscription(int cardId, in DownloadableSubscription subscription,
         boolean switchAfterDownload, String callingPackage, in Bundle resolvedBundle,
diff --git a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java
index 02a439b..2310c82 100644
--- a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java
+++ b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java
@@ -17,17 +17,30 @@
 package com.android.tests.rollback.testapp;
 
 import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
 import android.os.Bundle;
 
 /**
  * A crashing test app for testing apk rollback support.
  */
 public class CrashingMainActivity extends Activity {
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
+        incrementCountAndBroadcast();
         throw new RuntimeException("Intended force crash");
     }
+
+    public void incrementCountAndBroadcast() {
+        SharedPreferences preferences = getSharedPreferences("prefs", Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = preferences.edit();
+        int count = preferences.getInt("crash_count", 0);
+        editor.putInt("crash_count", ++count).commit();
+
+        Intent intent = new Intent("com.android.tests.rollback.CRASH");
+        intent.putExtra("count", count);
+        sendBroadcast(intent);
+    }
 }
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index e128a6c..4b277ae 100644
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -17,6 +17,7 @@
 package com.android.tests.rollback;
 
 import android.Manifest;
+import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -36,7 +37,6 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -45,6 +45,7 @@
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -413,7 +414,6 @@
 
     /**
      * Test that app user data is rolled back.
-     * TODO: Stop ignoring this test once user data rollback is supported.
      */
     @Test
     public void testUserDataRollback() throws Exception {
@@ -568,9 +568,7 @@
     }
 
     /**
-     * Test rollback of multi-package installs.
-     * TODO: Stop ignoring this test once support for multi-package rollback
-     * is implemented.
+     * Test rollback of multi-package installs is implemented.
      */
     @Test
     public void testMultiPackage() throws Exception {
@@ -630,18 +628,20 @@
         assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode());
     }
 
-    // TODO(zezeozue): Stop ignoring after fixing race between rolling back and testing version
     /**
      * Test bad update automatic rollback.
      */
-    @Ignore("Flaky")
     @Test
     public void testBadUpdateRollback() throws Exception {
+        BroadcastReceiver crashCountReceiver = null;
+        Context context = InstrumentationRegistry.getContext();
         try {
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.MANAGE_ROLLBACKS,
+                    Manifest.permission.KILL_BACKGROUND_PROCESSES,
+                    Manifest.permission.RESTART_PACKAGES);
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
 
             // Prep installation of the test apps.
@@ -669,23 +669,52 @@
                     rm.getAvailableRollbacks(), TEST_APP_B);
             assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB);
 
+            BlockingQueue<Integer> crashQueue = new SynchronousQueue<>();
+
+            IntentFilter crashCountFilter = new IntentFilter();
+            crashCountFilter.addAction("com.android.tests.rollback.CRASH");
+            crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT);
+
+            crashCountReceiver = new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        try {
+                            // Sleep long enough for packagewatchdog to be notified of crash
+                            Thread.sleep(1000);
+                            // Kill app and close AppErrorDialog
+                            ActivityManager am = context.getSystemService(ActivityManager.class);
+                            am.killBackgroundProcesses(TEST_APP_A);
+                            // Allow another package launch
+                            crashQueue.offer(intent.getIntExtra("count", 0), 5, TimeUnit.SECONDS);
+                        } catch (InterruptedException e) {
+                            fail("Failed to communicate with test app");
+                        }
+                    }
+                };
+            context.registerReceiver(crashCountReceiver, crashCountFilter);
+
             // Start apps PackageWatchdog#TRIGGER_FAILURE_COUNT times so TEST_APP_A crashes
-            for (int i = 0; i < 5; i++) {
+            Integer crashCount = null;
+            do {
                 RollbackTestUtils.launchPackage(TEST_APP_A);
-                Thread.sleep(1000);
-            }
-            Thread.sleep(1000);
+                crashCount = crashQueue.poll(5, TimeUnit.SECONDS);
+                if (crashCount == null) {
+                    fail("Timed out waiting for crash signal from test app");
+                }
+            } while(crashCount < 5);
 
             // TEST_APP_A is automatically rolled back by the RollbackPackageHealthObserver
             assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
             // Instrumented app is still the package installer
-            Context context = InstrumentationRegistry.getContext();
             String installer = context.getPackageManager().getInstallerPackageName(TEST_APP_A);
             assertEquals(INSTRUMENTED_APP, installer);
             // TEST_APP_B is untouched
             assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
         } finally {
             RollbackTestUtils.dropShellPermissionIdentity();
+            if (crashCountReceiver != null) {
+                context.unregisterReceiver(crashCountReceiver);
+            }
         }
     }
 
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 3127d74..50468cb 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -922,6 +922,7 @@
             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
             mConnected = true;
             mConfig = new VpnConfig();
+            mConfig.isMetered = false;
         }
 
         @Override
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 5b17224..46de3d0 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -168,6 +168,8 @@
         ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT;
         when(mContext.getApplicationInfo()).thenReturn(applicationInfo);
+        when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+                .thenReturn(applicationInfo);
 
         doNothing().when(mNetService).registerObserver(any());
     }
@@ -544,23 +546,28 @@
         final Network wifi = new Network(2);
 
         final Map<Network, NetworkCapabilities> networks = new HashMap<>();
-        networks.put(mobile, new NetworkCapabilities()
-                .addTransportType(TRANSPORT_CELLULAR)
-                .addCapability(NET_CAPABILITY_INTERNET)
-                .addCapability(NET_CAPABILITY_NOT_METERED)
-                .addCapability(NET_CAPABILITY_NOT_CONGESTED)
-                .setLinkDownstreamBandwidthKbps(10));
-        networks.put(wifi, new NetworkCapabilities()
-                .addTransportType(TRANSPORT_WIFI)
-                .addCapability(NET_CAPABILITY_INTERNET)
-                .addCapability(NET_CAPABILITY_NOT_ROAMING)
-                .addCapability(NET_CAPABILITY_NOT_CONGESTED)
-                .setLinkUpstreamBandwidthKbps(20));
+        networks.put(
+                mobile,
+                new NetworkCapabilities()
+                        .addTransportType(TRANSPORT_CELLULAR)
+                        .addCapability(NET_CAPABILITY_INTERNET)
+                        .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+                        .setLinkDownstreamBandwidthKbps(10));
+        networks.put(
+                wifi,
+                new NetworkCapabilities()
+                        .addTransportType(TRANSPORT_WIFI)
+                        .addCapability(NET_CAPABILITY_INTERNET)
+                        .addCapability(NET_CAPABILITY_NOT_METERED)
+                        .addCapability(NET_CAPABILITY_NOT_ROAMING)
+                        .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+                        .setLinkUpstreamBandwidthKbps(20));
         setMockedNetworks(networks);
 
         final NetworkCapabilities caps = new NetworkCapabilities();
 
-        Vpn.updateCapabilities(mConnectivityManager, new Network[] { }, caps);
+        Vpn.updateCapabilities(
+                mConnectivityManager, new Network[] {}, caps, false /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
         assertFalse(caps.hasTransport(TRANSPORT_WIFI));
@@ -570,17 +577,33 @@
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile }, caps);
+        Vpn.updateCapabilities(
+                mConnectivityManager,
+                new Network[] {mobile},
+                caps,
+                false /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
         assertFalse(caps.hasTransport(TRANSPORT_WIFI));
         assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
         assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(mConnectivityManager, new Network[] { wifi }, caps);
+        Vpn.updateCapabilities(
+                mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */);
+        assertTrue(caps.hasTransport(TRANSPORT_VPN));
+        assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
+        assertTrue(caps.hasTransport(TRANSPORT_WIFI));
+        assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
+        assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+
+        Vpn.updateCapabilities(
+                mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
         assertTrue(caps.hasTransport(TRANSPORT_WIFI));
@@ -590,7 +613,11 @@
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile, wifi }, caps);
+        Vpn.updateCapabilities(
+                mConnectivityManager,
+                new Network[] {mobile, wifi},
+                caps,
+                false /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
         assertTrue(caps.hasTransport(TRANSPORT_WIFI));
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 3c3edda..672731c 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -301,6 +301,7 @@
                         break;
                     }
                     // This is not alphabetical, so we fall through to variant
+                    [[fallthrough]];
                 case 5:
                 case 6:
                 case 7:
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 17847ea..145e269 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -23,17 +23,9 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import java.io.ByteArrayInputStream;
 import java.nio.charset.StandardCharsets;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -1126,6 +1118,12 @@
             String value = PASSWORD_KEY.equals(key) ? "<removed>" : mFields.get(key);
             sb.append(key).append(" ").append(value).append("\n");
         }
+        if (mEapMethod >= 0 && mEapMethod < Eap.strings.length) {
+            sb.append("eap_method: ").append(Eap.strings[mEapMethod]).append("\n");
+        }
+        if (mPhase2Method > 0 && mPhase2Method < Phase2.strings.length) {
+            sb.append("phase2_method: ").append(Phase2.strings[mPhase2Method]).append("\n");
+        }
         return sb.toString();
     }