Merge "Update boot classpath and system server profiles"
diff --git a/api/current.txt b/api/current.txt
index 0176c68..f1b5459 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5262,7 +5262,7 @@
     method public int describeContents();
     method public boolean getAllowSystemGeneratedContextualActions();
     method public int getBadgeIconType();
-    method public android.app.Notification.BubbleMetadata getBubbleMetadata();
+    method @Nullable public android.app.Notification.BubbleMetadata getBubbleMetadata();
     method public String getChannelId();
     method public String getGroup();
     method public int getGroupAlertBehavior();
@@ -5479,25 +5479,25 @@
   public static final class Notification.BubbleMetadata implements android.os.Parcelable {
     method public int describeContents();
     method public boolean getAutoExpandBubble();
-    method public android.app.PendingIntent getDeleteIntent();
+    method @Nullable public android.app.PendingIntent getDeleteIntent();
     method public int getDesiredHeight();
-    method public android.graphics.drawable.Icon getIcon();
-    method public android.app.PendingIntent getIntent();
+    method @NonNull public android.graphics.drawable.Icon getIcon();
+    method @NonNull public android.app.PendingIntent getIntent();
     method public boolean getSuppressInitialNotification();
     method @Deprecated public CharSequence getTitle();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.Notification.BubbleMetadata> CREATOR;
   }
 
-  public static class Notification.BubbleMetadata.Builder {
+  public static final class Notification.BubbleMetadata.Builder {
     ctor public Notification.BubbleMetadata.Builder();
-    method public android.app.Notification.BubbleMetadata build();
-    method public android.app.Notification.BubbleMetadata.Builder setAutoExpandBubble(boolean);
-    method public android.app.Notification.BubbleMetadata.Builder setDeleteIntent(android.app.PendingIntent);
-    method public android.app.Notification.BubbleMetadata.Builder setDesiredHeight(int);
-    method public android.app.Notification.BubbleMetadata.Builder setIcon(android.graphics.drawable.Icon);
-    method public android.app.Notification.BubbleMetadata.Builder setIntent(android.app.PendingIntent);
-    method public android.app.Notification.BubbleMetadata.Builder setSuppressInitialNotification(boolean);
+    method @NonNull public android.app.Notification.BubbleMetadata build();
+    method @NonNull public android.app.Notification.BubbleMetadata.Builder setAutoExpandBubble(boolean);
+    method @NonNull public android.app.Notification.BubbleMetadata.Builder setDeleteIntent(@Nullable android.app.PendingIntent);
+    method @NonNull public android.app.Notification.BubbleMetadata.Builder setDesiredHeight(int);
+    method @NonNull public android.app.Notification.BubbleMetadata.Builder setIcon(@NonNull android.graphics.drawable.Icon);
+    method @NonNull public android.app.Notification.BubbleMetadata.Builder setIntent(@NonNull android.app.PendingIntent);
+    method @NonNull public android.app.Notification.BubbleMetadata.Builder setSuppressInitialNotification(boolean);
     method @Deprecated public android.app.Notification.BubbleMetadata.Builder setTitle(CharSequence);
   }
 
@@ -5522,7 +5522,7 @@
     method @NonNull public android.app.Notification.Builder setAllowSystemGeneratedContextualActions(boolean);
     method @NonNull public android.app.Notification.Builder setAutoCancel(boolean);
     method @NonNull public android.app.Notification.Builder setBadgeIconType(int);
-    method @NonNull public android.app.Notification.Builder setBubbleMetadata(android.app.Notification.BubbleMetadata);
+    method @NonNull public android.app.Notification.Builder setBubbleMetadata(@Nullable android.app.Notification.BubbleMetadata);
     method @NonNull public android.app.Notification.Builder setCategory(String);
     method @NonNull public android.app.Notification.Builder setChannelId(String);
     method @NonNull public android.app.Notification.Builder setChronometerCountDown(boolean);
@@ -12284,6 +12284,7 @@
     method public final void flushLayoutCache();
     method @NonNull public android.content.res.XmlResourceParser getAnimation(@AnimatorRes @AnimRes int) throws android.content.res.Resources.NotFoundException;
     method public final android.content.res.AssetManager getAssets();
+    method @AnyRes public static int getAttributeSetSourceResId(@Nullable android.util.AttributeSet);
     method public boolean getBoolean(@BoolRes int) throws android.content.res.Resources.NotFoundException;
     method @Deprecated @ColorInt public int getColor(@ColorRes int) throws android.content.res.Resources.NotFoundException;
     method @ColorInt public int getColor(@ColorRes int, @Nullable android.content.res.Resources.Theme) throws android.content.res.Resources.NotFoundException;
@@ -29944,6 +29945,8 @@
     method public int getLinkSpeed();
     method public String getMacAddress();
     method public int getNetworkId();
+    method @Nullable public String getPasspointFqdn();
+    method @Nullable public String getPasspointProviderFriendlyName();
     method public int getRssi();
     method @IntRange(from=0xffffffff) public int getRxLinkSpeedMbps();
     method public String getSSID();
@@ -35493,6 +35496,7 @@
     field public static final String DISALLOW_CONFIG_VPN = "no_config_vpn";
     field public static final String DISALLOW_CONFIG_WIFI = "no_config_wifi";
     field public static final String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
+    field public static final String DISALLOW_CONTENT_SUGGESTIONS = "no_content_suggestions";
     field public static final String DISALLOW_CREATE_WINDOWS = "no_create_windows";
     field public static final String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
     field public static final String DISALLOW_DATA_ROAMING = "no_data_roaming";
@@ -49197,7 +49201,6 @@
     method public final boolean isFunctionPressed();
     method public static final boolean isGamepadButton(int);
     method public final boolean isLongPress();
-    method public static final boolean isMediaSessionKey(int);
     method public final boolean isMetaPressed();
     method public static boolean isModifierKey(int);
     method public final boolean isNumLockOn();
@@ -50077,7 +50080,7 @@
   }
 
   public class Surface implements android.os.Parcelable {
-    ctor public Surface(android.view.SurfaceControl);
+    ctor public Surface(@NonNull android.view.SurfaceControl);
     ctor public Surface(android.graphics.SurfaceTexture);
     method public int describeContents();
     method public boolean isValid();
@@ -50111,10 +50114,10 @@
 
   public static class SurfaceControl.Builder {
     ctor public SurfaceControl.Builder();
-    method public android.view.SurfaceControl build();
-    method public android.view.SurfaceControl.Builder setBufferSize(@IntRange(from=0) int, @IntRange(from=0) int);
+    method @NonNull public android.view.SurfaceControl build();
+    method @NonNull public android.view.SurfaceControl.Builder setBufferSize(@IntRange(from=0) int, @IntRange(from=0) int);
     method @NonNull public android.view.SurfaceControl.Builder setFormat(int);
-    method public android.view.SurfaceControl.Builder setName(String);
+    method @NonNull public android.view.SurfaceControl.Builder setName(@NonNull String);
     method @NonNull public android.view.SurfaceControl.Builder setOpaque(boolean);
     method @NonNull public android.view.SurfaceControl.Builder setParent(@Nullable android.view.SurfaceControl);
   }
@@ -54512,7 +54515,7 @@
     method public abstract boolean getDomStorageEnabled();
     method public abstract String getFantasyFontFamily();
     method public abstract String getFixedFontFamily();
-    method public int getForceDarkMode();
+    method public int getForceDark();
     method public abstract boolean getJavaScriptCanOpenWindowsAutomatically();
     method public abstract boolean getJavaScriptEnabled();
     method public abstract android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm();
@@ -54559,7 +54562,7 @@
     method @Deprecated public abstract void setEnableSmoothTransition(boolean);
     method public abstract void setFantasyFontFamily(String);
     method public abstract void setFixedFontFamily(String);
-    method public void setForceDarkMode(int);
+    method public void setForceDark(int);
     method @Deprecated public abstract void setGeolocationDatabasePath(String);
     method public abstract void setGeolocationEnabled(boolean);
     method public abstract void setJavaScriptCanOpenWindowsAutomatically(boolean);
@@ -54590,9 +54593,9 @@
     method public abstract void setUserAgentString(@Nullable String);
     method public abstract boolean supportMultipleWindows();
     method public abstract boolean supportZoom();
-    field public static final int FORCE_DARK_AUTO = 0; // 0x0
-    field public static final int FORCE_DARK_OFF = -1; // 0xffffffff
-    field public static final int FORCE_DARK_ON = 1; // 0x1
+    field public static final int FORCE_DARK_AUTO = 1; // 0x1
+    field public static final int FORCE_DARK_OFF = 0; // 0x0
+    field public static final int FORCE_DARK_ON = 2; // 0x2
     field public static final int LOAD_CACHE_ELSE_NETWORK = 1; // 0x1
     field public static final int LOAD_CACHE_ONLY = 3; // 0x3
     field public static final int LOAD_DEFAULT = -1; // 0xffffffff
@@ -54715,8 +54718,8 @@
     method @NonNull public static ClassLoader getWebViewClassLoader();
     method public android.webkit.WebViewClient getWebViewClient();
     method @NonNull public android.os.Looper getWebViewLooper();
-    method @Nullable public android.webkit.WebViewRenderer getWebViewRenderer();
-    method @Nullable public android.webkit.WebViewRendererClient getWebViewRendererClient();
+    method @Nullable public android.webkit.WebViewRenderProcess getWebViewRenderProcess();
+    method @Nullable public android.webkit.WebViewRenderProcessClient getWebViewRenderProcessClient();
     method public void goBack();
     method public void goBackOrForward(int);
     method public void goForward();
@@ -54766,8 +54769,8 @@
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
     method public void setWebViewClient(android.webkit.WebViewClient);
-    method public void setWebViewRendererClient(@NonNull java.util.concurrent.Executor, @NonNull android.webkit.WebViewRendererClient);
-    method public void setWebViewRendererClient(@Nullable android.webkit.WebViewRendererClient);
+    method public void setWebViewRenderProcessClient(@NonNull java.util.concurrent.Executor, @NonNull android.webkit.WebViewRenderProcessClient);
+    method public void setWebViewRenderProcessClient(@Nullable android.webkit.WebViewRenderProcessClient);
     method @Deprecated public boolean shouldDelayChildPressedState();
     method @Deprecated public boolean showFindDialog(@Nullable String, boolean);
     method public static void startSafeBrowsing(@NonNull android.content.Context, @Nullable android.webkit.ValueCallback<java.lang.Boolean>);
@@ -54883,14 +54886,15 @@
     method @Deprecated public android.webkit.WebView getWebView();
   }
 
-  public abstract class WebViewRenderer {
+  public abstract class WebViewRenderProcess {
+    ctor public WebViewRenderProcess();
     method public abstract boolean terminate();
   }
 
-  public abstract class WebViewRendererClient {
-    ctor public WebViewRendererClient();
-    method public abstract void onRendererResponsive(@NonNull android.webkit.WebView, @Nullable android.webkit.WebViewRenderer);
-    method public abstract void onRendererUnresponsive(@NonNull android.webkit.WebView, @Nullable android.webkit.WebViewRenderer);
+  public abstract class WebViewRenderProcessClient {
+    ctor public WebViewRenderProcessClient();
+    method public abstract void onRenderProcessResponsive(@NonNull android.webkit.WebView, @Nullable android.webkit.WebViewRenderProcess);
+    method public abstract void onRenderProcessUnresponsive(@NonNull android.webkit.WebView, @Nullable android.webkit.WebViewRenderProcess);
   }
 
 }
diff --git a/api/system-current.txt b/api/system-current.txt
index 232144f..04bddc1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -231,7 +231,6 @@
   }
 
   public static final class R.dimen {
-    field public static final int config_mediaMetadataBitmapMaxSize = 17104904; // 0x1050008
     field public static final int config_restrictedIconSize = 17104903; // 0x1050007
   }
 
@@ -3495,7 +3494,6 @@
     field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
     field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
     field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
-    field public static final int FLAG_FROM_KEY = 65536; // 0x10000
     field public static final int SUCCESS = 0; // 0x0
   }
 
@@ -4734,8 +4732,6 @@
   }
 
   public class WifiInfo implements android.os.Parcelable {
-    method @Nullable public String getFqdn();
-    method @Nullable public String getProviderFriendlyName();
     method public boolean isOsuAp();
     method public boolean isPasspointAp();
   }
@@ -5602,7 +5598,6 @@
   }
 
   public class UserManager {
-    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean canSwitchUsers();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void clearSeedAccountData();
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountName();
@@ -5612,6 +5607,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.graphics.Bitmap getUserIcon();
     method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
+    method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public int getUserSwitchability();
     method public boolean hasRestrictedProfiles();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isAdminUser();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isGuestUser();
@@ -5619,7 +5615,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedProfile(int);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isPrimaryUser();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean removeUser(android.os.UserHandle);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean removeUser(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(@Nullable String);
     field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
@@ -5629,6 +5625,10 @@
     field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2
     field public static final int RESTRICTION_SOURCE_PROFILE_OWNER = 4; // 0x4
     field public static final int RESTRICTION_SOURCE_SYSTEM = 1; // 0x1
+    field public static final int SWITCHABILITY_STATUS_OK = 0; // 0x0
+    field public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 4; // 0x4
+    field public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1; // 0x1
+    field public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 2; // 0x2
   }
 
   public static final class UserManager.EnforcingUser implements android.os.Parcelable {
@@ -9846,8 +9846,8 @@
     method public int getVisibleTitleHeight();
     method public android.webkit.WebChromeClient getWebChromeClient();
     method public android.webkit.WebViewClient getWebViewClient();
-    method public android.webkit.WebViewRenderer getWebViewRenderer();
-    method public android.webkit.WebViewRendererClient getWebViewRendererClient();
+    method @Nullable public android.webkit.WebViewRenderProcess getWebViewRenderProcess();
+    method @Nullable public android.webkit.WebViewRenderProcessClient getWebViewRenderProcessClient();
     method public android.view.View getZoomControls();
     method public void goBack();
     method public void goBackOrForward(int);
@@ -9897,7 +9897,7 @@
     method public void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public void setWebViewClient(android.webkit.WebViewClient);
-    method public void setWebViewRendererClient(@Nullable java.util.concurrent.Executor, @Nullable android.webkit.WebViewRendererClient);
+    method public void setWebViewRenderProcessClient(@Nullable java.util.concurrent.Executor, @Nullable android.webkit.WebViewRenderProcessClient);
     method public boolean showFindDialog(String, boolean);
     method public void stopLoading();
     method public boolean zoomBy(float);
@@ -9979,10 +9979,6 @@
     field public final android.content.pm.Signature[] signatures;
   }
 
-  public abstract class WebViewRenderer {
-    ctor public WebViewRenderer();
-  }
-
   public final class WebViewUpdateService {
     method public static android.webkit.WebViewProviderInfo[] getAllWebViewPackages();
     method public static String getCurrentWebViewPackageName();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 03806fa..a8a34d2 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3177,6 +3177,7 @@
      * Returns the bubble metadata that will be used to display app content in a floating window
      * over the existing foreground activity.
      */
+    @Nullable
     public BubbleMetadata getBubbleMetadata() {
         return mBubbleMetadata;
     }
@@ -3568,7 +3569,7 @@
          * collapsed state, the bubble intent will be invoked and displayed.</b>
          */
         @NonNull
-        public Builder setBubbleMetadata(BubbleMetadata data) {
+        public Builder setBubbleMetadata(@Nullable BubbleMetadata data) {
             mN.mBubbleMetadata = data;
             return this;
         }
@@ -8562,6 +8563,7 @@
         /**
          * @return the pending intent used to populate the floating window for this bubble.
          */
+        @NonNull
         public PendingIntent getIntent() {
             return mPendingIntent;
         }
@@ -8569,6 +8571,7 @@
         /**
          * @return the pending intent to send when the bubble is dismissed by a user, if one exists.
          */
+        @Nullable
         public PendingIntent getDeleteIntent() {
             return mDeleteIntent;
         }
@@ -8583,9 +8586,11 @@
         public CharSequence getTitle() {
             return "";
         }
+
         /**
          * @return the icon that will be displayed for this bubble when it is collapsed.
          */
+        @NonNull
         public Icon getIcon() {
             return mIcon;
         }
@@ -8654,7 +8659,7 @@
         /**
          * Builder to construct a {@link BubbleMetadata} object.
          */
-        public static class Builder {
+        public static final class Builder {
 
             private PendingIntent mPendingIntent;
             private Icon mIcon;
@@ -8672,7 +8677,8 @@
              * Sets the intent that will be used when the bubble is expanded. This will display the
              * app content in a floating window over the existing foreground activity.
              */
-            public BubbleMetadata.Builder setIntent(PendingIntent intent) {
+            @NonNull
+            public BubbleMetadata.Builder setIntent(@NonNull PendingIntent intent) {
                 if (intent == null) {
                     throw new IllegalArgumentException("Bubble requires non-null pending intent");
                 }
@@ -8700,7 +8706,8 @@
              * If your app produces multiple bubbles, the image should be unique for each of them.
              * </p>
              */
-            public BubbleMetadata.Builder setIcon(Icon icon) {
+            @NonNull
+            public BubbleMetadata.Builder setIcon(@NonNull Icon icon) {
                 if (icon == null) {
                     throw new IllegalArgumentException("Bubbles require non-null icon");
                 }
@@ -8713,6 +8720,7 @@
              * {@link #setIntent(PendingIntent)}, this height may not be respected if there is not
              * enough space on the screen or if the provided height is too small to be useful.
              */
+            @NonNull
             public BubbleMetadata.Builder setDesiredHeight(int height) {
                 mDesiredHeight = Math.max(height, 0);
                 return this;
@@ -8729,6 +8737,7 @@
              * <p>Generally this flag should only be set if the user has performed an action to
              * request or create a bubble.</p>
              */
+            @NonNull
             public BubbleMetadata.Builder setAutoExpandBubble(boolean shouldExpand) {
                 setFlag(FLAG_AUTO_EXPAND_BUBBLE, shouldExpand);
                 return this;
@@ -8745,6 +8754,7 @@
              * <p>Generally this flag should only be set if the user has performed an action to
              * request or create a bubble.</p>
              */
+            @NonNull
             public BubbleMetadata.Builder setSuppressInitialNotification(
                     boolean shouldSupressNotif) {
                 setFlag(FLAG_SUPPRESS_INITIAL_NOTIFICATION, shouldSupressNotif);
@@ -8754,7 +8764,8 @@
             /**
              * Sets an optional intent to send when this bubble is explicitly removed by the user.
              */
-            public BubbleMetadata.Builder setDeleteIntent(PendingIntent deleteIntent) {
+            @NonNull
+            public BubbleMetadata.Builder setDeleteIntent(@Nullable PendingIntent deleteIntent) {
                 mDeleteIntent = deleteIntent;
                 return this;
             }
@@ -8764,6 +8775,7 @@
              * <p>Will throw {@link IllegalStateException} if required fields have not been set
              * on this builder.</p>
              */
+            @NonNull
             public BubbleMetadata build() {
                 if (mPendingIntent == null) {
                     throw new IllegalStateException("Must supply pending intent to bubble");
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c855d45..6729242 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1396,9 +1396,11 @@
 
 
     /**
+     * Returns the resource ID of the resource that was used to create this AttributeSet.
+     *
      * @param set AttributeSet for which we want to find the source.
-     * @return The resource id for the source that is backing the given AttributeSet
-     * @hide
+     * @return The resource ID for the source that is backing the given AttributeSet or
+     * {@link Resources#ID_NULL} if the AttributeSet is {@code null}.
      */
     @AnyRes
     public static int getAttributeSetSourceResId(@Nullable AttributeSet set) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b7e65b9..e4277e4 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -4761,6 +4761,9 @@
         sb.append(")");
         pw.println(sb.toString());
 
+        printControllerActivity(pw, sb, prefix, CELLULAR_CONTROLLER_NAME,
+                getModemControllerActivity(), which);
+
         pw.print("     Cellular data received: "); pw.println(formatBytesLocked(mobileRxTotalBytes));
         pw.print("     Cellular data sent: "); pw.println(formatBytesLocked(mobileTxTotalBytes));
         pw.print("     Cellular packets received: "); pw.println(mobileRxTotalPackets);
@@ -4818,9 +4821,6 @@
         if (!didOne) sb.append(" (no activity)");
         pw.println(sb.toString());
 
-        printControllerActivity(pw, sb, prefix, CELLULAR_CONTROLLER_NAME,
-            getModemControllerActivity(), which);
-
         pw.print(prefix);
         sb.setLength(0);
         sb.append(prefix);
@@ -4837,6 +4837,9 @@
         sb.append(")");
         pw.println(sb.toString());
 
+        printControllerActivity(pw, sb, prefix, WIFI_CONTROLLER_NAME,
+                getWifiControllerActivity(), which);
+
         pw.print("     Wifi data received: "); pw.println(formatBytesLocked(wifiRxTotalBytes));
         pw.print("     Wifi data sent: "); pw.println(formatBytesLocked(wifiTxTotalBytes));
         pw.print("     Wifi packets received: "); pw.println(wifiRxTotalPackets);
@@ -4914,9 +4917,6 @@
         if (!didOne) sb.append(" (no activity)");
         pw.println(sb.toString());
 
-        printControllerActivity(pw, sb, prefix, WIFI_CONTROLLER_NAME,
-            getWifiControllerActivity(), which);
-
         pw.print(prefix);
         sb.setLength(0);
         sb.append(prefix);
@@ -4949,8 +4949,10 @@
             pw.print(prefix);
             sb.setLength(0);
             sb.append(prefix);
-            sb.append("     Battery Drain (mAh): ");
-            sb.append(Double.toString(((double) gpsBatteryDrainMaMs)/(3600 * 1000)));
+            sb.append("     GPS Battery Drain: ");
+            sb.append(new DecimalFormat("#.##").format(
+                    ((double) gpsBatteryDrainMaMs) / (3600 * 1000)));
+            sb.append("mAh");
             pw.println(sb.toString());
         }
 
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 4263377..185df5e 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
 import android.app.Activity;
@@ -954,6 +955,21 @@
     public static final String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
 
     /**
+     * Specifies if the current user is able to receive content suggestions for selections based on
+     * the contents of their screen.
+     *
+     * <p>Device owner and profile owner can set this restriction. When it is set by device owner,
+     * only the target user will be affected.
+     *
+     * <p>The default value is <code>false</code>.
+     *
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_CONTENT_SUGGESTIONS = "no_content_suggestions";
+
+    /**
      * Specifies if user switching is blocked on the current user.
      *
      * <p> This restriction can only be set by the device owner, it will be applied to all users.
@@ -1102,6 +1118,47 @@
     public static final int USER_CREATION_FAILED_NO_MORE_USERS = Activity.RESULT_FIRST_USER + 1;
 
     /**
+     * Indicates that users are switchable.
+     * @hide
+     */
+    @SystemApi
+    public static final int SWITCHABILITY_STATUS_OK = 0;
+
+    /**
+     * Indicated that the user is in a phone call.
+     * @hide
+     */
+    @SystemApi
+    public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1 << 0;
+
+    /**
+     * Indicates that user switching is disallowed ({@link #DISALLOW_USER_SWITCH} is set).
+     * @hide
+     */
+    @SystemApi
+    public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 1 << 1;
+
+    /**
+     * Indicates that the system user is locked and user switching is not allowed.
+     * @hide
+     */
+    @SystemApi
+    public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 1 << 2;
+
+    /**
+     * Result returned in {@link #getUserSwitchability()} indicating user swichability.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = { "SWITCHABILITY_STATUS_" }, value = {
+            SWITCHABILITY_STATUS_OK,
+            SWITCHABILITY_STATUS_USER_IN_CALL,
+            SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED,
+            SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED
+    })
+    public @interface UserSwitchabilityResult {}
+
+    /**
      * Indicates user operation is successful.
      */
     public static final int USER_OPERATION_SUCCESS = 0;
@@ -1223,14 +1280,13 @@
     }
 
     /**
-     * Returns whether switching users is currently allowed.
-     * <p>For instance switching users is not allowed if the current user is in a phone call,
-     * system user hasn't been unlocked yet, or {@link #DISALLOW_USER_SWITCH} is set.
+     * @deprecated use {@link #getUserSwitchability()} instead.
+     *
+     * @removed
      * @hide
      */
-    @SystemApi
-    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
-            android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+    @Deprecated
+    @UnsupportedAppUsage
     public boolean canSwitchUsers() {
         boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
                 mContext.getContentResolver(),
@@ -1244,6 +1300,42 @@
     }
 
     /**
+     * Returns whether switching users is currently allowed.
+     * <p>
+     * Switching users is not allowed in the following cases:
+     * <li>the user is in a phone call</li>
+     * <li>{@link #DISALLOW_USER_SWITCH} is set</li>
+     * <li>system user hasn't been unlocked yet</li>
+     *
+     * @return A {@link UserSwitchabilityResult} flag indicating if the user is switchable.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(allOf = {Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+    public @UserSwitchabilityResult int getUserSwitchability() {
+        final boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
+                mContext.getContentResolver(),
+                Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
+        final boolean systemUserUnlocked = isUserUnlocked(UserHandle.SYSTEM);
+        final TelephonyManager tm =
+                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+
+        int flags = SWITCHABILITY_STATUS_OK;
+        if (tm.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
+            flags |= SWITCHABILITY_STATUS_USER_IN_CALL;
+        }
+        if (hasUserRestriction(DISALLOW_USER_SWITCH)) {
+            flags |= SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED;
+        }
+        if (!allowUserSwitchingWhenSystemUserLocked && !systemUserUnlocked) {
+            flags |= SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED;
+        }
+        return flags;
+    }
+
+    /**
      * Returns the user handle for the user that this process is running under.
      *
      * @return the user handle of this process.
@@ -2655,11 +2747,16 @@
      * Removes a user and all associated data.
      *
      * @param user the user that needs to be removed.
+     * @return {@code true} if the user was successfully removed, {@code false} otherwise.
+     * @throws IllegalArgumentException if {@code user} is {@code null}
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
-    public boolean removeUser(UserHandle user) {
+    public boolean removeUser(@NonNull UserHandle user) {
+        if (user == null) {
+            throw new IllegalArgumentException("user cannot be null");
+        }
         return removeUser(user.getIdentifier());
     }
 
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 1382fbc..2d7e179 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -142,6 +142,10 @@
                 && legacyContentInsets != null && legacyStableInsets != null) {
             WindowInsets.assignCompatInsets(typeInsetsMap, legacyContentInsets);
             WindowInsets.assignCompatInsets(typeMaxInsetsMap, legacyStableInsets);
+
+            // TODO: set system gesture insets based on actual system gesture area.
+            typeInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyContentInsets);
+            typeMaxInsetsMap[Type.indexOf(Type.systemGestures())] = Insets.of(legacyContentInsets);
         }
         for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
             InsetsSource source = mSources.get(type);
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index f700d32..87dd5b4 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1806,28 +1806,6 @@
     }
 
     /**
-     * Returns whether this key will be sent to the
-     * {@link android.media.session.MediaSession.Callback} if not handled.
-     */
-    public static final boolean isMediaSessionKey(int keyCode) {
-        switch (keyCode) {
-            case KeyEvent.KEYCODE_MEDIA_PLAY:
-            case KeyEvent.KEYCODE_MEDIA_PAUSE:
-            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-            case KeyEvent.KEYCODE_MUTE:
-            case KeyEvent.KEYCODE_HEADSETHOOK:
-            case KeyEvent.KEYCODE_MEDIA_STOP:
-            case KeyEvent.KEYCODE_MEDIA_NEXT:
-            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-            case KeyEvent.KEYCODE_MEDIA_REWIND:
-            case KeyEvent.KEYCODE_MEDIA_RECORD:
-            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
-                return true;
-        }
-        return false;
-    }
-
-    /**
      * Returns true if the specified keycode is a gamepad button.
      * @return True if the keycode is a gamepad button, such as {@link #KEYCODE_BUTTON_A}.
      */
@@ -1886,6 +1864,30 @@
         }
     }
 
+    /**
+     * Returns whether this key will be sent to the
+     * {@link android.media.session.MediaSession.Callback} if not handled.
+     *
+     * @hide
+     */
+    public static final boolean isMediaSessionKey(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_MEDIA_PLAY:
+            case KeyEvent.KEYCODE_MEDIA_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+            case KeyEvent.KEYCODE_MUTE:
+            case KeyEvent.KEYCODE_HEADSETHOOK:
+            case KeyEvent.KEYCODE_MEDIA_STOP:
+            case KeyEvent.KEYCODE_MEDIA_NEXT:
+            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+            case KeyEvent.KEYCODE_MEDIA_REWIND:
+            case KeyEvent.KEYCODE_MEDIA_RECORD:
+            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+                return true;
+        }
+        return false;
+    }
+
     /** Is this a system key? System keys can not be used for menu shortcuts.
      * @hide
      */
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 6ff699e..cb64ab1 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
 import android.content.res.CompatibilityInfo.Translator;
 import android.graphics.Canvas;
@@ -193,7 +194,7 @@
      *
      * @param from The SurfaceControl to assosciate this Surface with
      */
-    public Surface(SurfaceControl from) {
+    public Surface(@NonNull SurfaceControl from) {
         copyFrom(from);
     }
 
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 5e2aaae..998ad2a 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -459,6 +459,7 @@
          * Construct a new {@link SurfaceControl} with the set parameters. The builder
          * remains valid.
          */
+        @NonNull
         public SurfaceControl build() {
             if (mWidth < 0 || mHeight < 0) {
                 throw new IllegalArgumentException(
@@ -477,7 +478,8 @@
          *
          * @param name A name to identify the Surface in debugging.
          */
-        public Builder setName(String name) {
+        @NonNull
+        public Builder setName(@NonNull String name) {
             mName = name;
             return this;
         }
@@ -488,6 +490,7 @@
          * @param width The buffer width in pixels.
          * @param height The buffer height in pixels.
          */
+        @NonNull
         public Builder setBufferSize(@IntRange(from = 0) int width,
                 @IntRange(from = 0) int height) {
             if (width < 0 || height < 0) {
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index f3bbca3..f1a992c 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -27,6 +27,7 @@
 import static android.view.WindowInsets.Type.all;
 import static android.view.WindowInsets.Type.compatSystemInsets;
 import static android.view.WindowInsets.Type.indexOf;
+import static android.view.WindowInsets.Type.systemGestures;
 
 import android.annotation.IntDef;
 import android.annotation.IntRange;
@@ -220,6 +221,8 @@
         }
         Insets[] typeInsetMap = new Insets[SIZE];
         assignCompatInsets(typeInsetMap, insets);
+        // TODO: set system gesture insets based on actual system gesture area.
+        typeInsetMap[indexOf(systemGestures())] = Insets.of(insets);
         return typeInsetMap;
     }
 
@@ -229,7 +232,6 @@
     static void assignCompatInsets(Insets[] typeInsetMap, Rect insets) {
         typeInsetMap[indexOf(TOP_BAR)] = Insets.of(0, insets.top, 0, 0);
         typeInsetMap[indexOf(SIDE_BARS)] = Insets.of(insets.left, 0, insets.right, insets.bottom);
-        typeInsetMap[indexOf(SYSTEM_GESTURES)] = Insets.of(insets);
     }
 
     private static boolean[] createCompatVisibilityMap(@Nullable Insets[] typeInsetMap) {
@@ -675,6 +677,7 @@
     public String toString() {
         return "WindowInsets{systemWindowInsets=" + getSystemWindowInsets()
                 + " stableInsets=" + getStableInsets()
+                + " sysGestureInsets=" + getSystemGestureInsets()
                 + (mDisplayCutout != null ? " cutout=" + mDisplayCutout : "")
                 + (isRound() ? " round" : "")
                 + "}";
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 8b98469..494eb03 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -231,34 +231,34 @@
             FORCE_DARK_ON
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface ForceDarkMode {}
+    public @interface ForceDark {}
 
     /**
-     * Used with {@link #setForceDarkMode}
+     * Used with {@link #setForceDark}
      *
      * Disable force dark, irrespective of the force dark mode of the WebView parent. In this mode,
      * WebView content will always be rendered as-is, regardless of whether native views are being
      * automatically darkened.
      */
-    public static final int FORCE_DARK_OFF = -1;
+    public static final int FORCE_DARK_OFF = 0;
 
     /**
-     * Used with {@link #setForceDarkMode}
+     * Used with {@link #setForceDark}
      *
      * Enable force dark, dependent on the state of the WebView parent. If the WebView parent view
      * is being automatically rendered in dark mode, then WebView content will be rendered so as to
      * emulate a dark theme. WebViews that are not attached to the view hierarchy will not be
      * inverted.
      */
-    public static final int FORCE_DARK_AUTO = 0;
+    public static final int FORCE_DARK_AUTO = 1;
 
     /**
-     * Used with {@link #setForceDarkMode}
+     * Used with {@link #setForceDark}
      *
      * Unconditionally enable force dark. In this mode WebView content will always be rendered so
      * as to emulate a dark theme.
      */
-    public static final int FORCE_DARK_ON = +1;
+    public static final int FORCE_DARK_ON = 2;
 
     /**
      * Enables dumping the pages navigation cache to a text file. The default
@@ -1467,7 +1467,7 @@
     /**
      * Set the force dark mode for this WebView.
      */
-    public void setForceDarkMode(@ForceDarkMode int forceDarkMode) {
+    public void setForceDark(@ForceDark int forceDark) {
         // Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
     }
 
@@ -1476,7 +1476,7 @@
      *
      * @return the currently set force dark mode.
      */
-    public @ForceDarkMode int getForceDarkMode() {
+    public @ForceDark int getForceDark() {
         // Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
         return FORCE_DARK_AUTO;
     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3555822..034cabd 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1704,7 +1704,7 @@
 
 
     /**
-     * Gets the WebView renderer associated with this WebView.
+     * Gets a handle to the WebView renderer process associated with this WebView.
      *
      * <p>In {@link android.os.Build.VERSION_CODES#O} and above, WebView may
      * run in "multiprocess" mode. In multiprocess mode, rendering of web
@@ -1717,67 +1717,70 @@
      * handle to the renderer process associated with the WebView, which can
      * be used to control the renderer process.
      *
-     * @return the {@link WebViewRenderer} renderer handle associated
+     * @return the {@link WebViewRenderProcess} renderer handle associated
      *         with this {@link WebView}, or {@code null} if
      *         WebView is not runing in multiprocess mode.
      */
     @Nullable
-    public WebViewRenderer getWebViewRenderer() {
+    public WebViewRenderProcess getWebViewRenderProcess() {
         checkThread();
-        return mProvider.getWebViewRenderer();
+        return mProvider.getWebViewRenderProcess();
     }
 
     /**
      * Sets the renderer client object associated with this WebView.
      *
      * <p>The renderer client encapsulates callbacks relevant to WebView renderer
-     * state. See {@link WebViewRendererClient} for details.
+     * state. See {@link WebViewRenderProcessClient} for details.
      *
      * <p>Although many WebView instances may share a single underlying
      * renderer, and renderers may live either in the application
      * process, or in a sandboxed process that is isolated from the
-     * application process, instances of {@link WebViewRendererClient}
+     * application process, instances of {@link WebViewRenderProcessClient}
      * are set per-WebView.  Callbacks represent renderer events from
      * the perspective of this WebView, and may or may not be correlated
      * with renderer events affecting other WebViews.
      *
-     * @param executor the Executor on which {@link WebViewRendererClient} callbacks will execute.
-     * @param webViewRendererClient the {@link WebViewRendererClient} object.
+     * @param executor the Executor on which {@link WebViewRenderProcessClient}
+     *                 callbacks will execute.
+     * @param webViewRenderProcessClient the {@link WebViewRenderProcessClient}
+     *                                   object.
      */
-    public void setWebViewRendererClient(
+    public void setWebViewRenderProcessClient(
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull WebViewRendererClient webViewRendererClient) {
+            @NonNull WebViewRenderProcessClient webViewRenderProcessClient) {
         checkThread();
-        mProvider.setWebViewRendererClient(executor, webViewRendererClient);
+        mProvider.setWebViewRenderProcessClient(
+                executor, webViewRenderProcessClient);
     }
 
     /**
      * Sets the renderer client object associated with this WebView.
      *
-     * See {@link #setWebViewRendererClient(Executor,WebViewRendererClient)} for details.
+     * See {@link #setWebViewRenderProcessClient(Executor,WebViewRenderProcessClient)} for details.
      *
-     * <p> {@link WebViewRendererClient} callbacks will run on the thread that this WebView was
+     * <p> {@link WebViewRenderProcessClient} callbacks will run on the thread that this WebView was
      * initialized on.
      *
-     * @param webViewRendererClient the {@link WebViewRendererClient} object.
+     * @param webViewRenderProcessClient the {@link WebViewRenderProcessClient} object.
      */
-    public void setWebViewRendererClient(
-            @Nullable WebViewRendererClient webViewRendererClient) {
+    public void setWebViewRenderProcessClient(
+            @Nullable WebViewRenderProcessClient webViewRenderProcessClient) {
         checkThread();
-        mProvider.setWebViewRendererClient(null, webViewRendererClient);
+        mProvider.setWebViewRenderProcessClient(null, webViewRenderProcessClient);
     }
 
     /**
      * Gets the renderer client object associated with this WebView.
      *
-     * @return the {@link WebViewRendererClient} object associated with this WebView, if one has
-     * been set via {@link #setWebViewRendererClient(WebViewRendererClient)} or {@code null}
-     * otherwise.
+     * @return the {@link WebViewRenderProcessClient} object associated with this WebView, if one
+     *         has been set via {@link #setWebViewRenderProcessClient(WebViewRenderProcessClient)}
+     *         or {@code null} otherwise.
      */
     @Nullable
-    public WebViewRendererClient getWebViewRendererClient() {
+    public WebViewRenderProcessClient getWebViewRenderProcessClient() {
         checkThread();
-        return mProvider.getWebViewRendererClient();
+        return mProvider.getWebViewRenderProcessClient();
     }
 
     /**
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 090640e..150fa88 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -102,9 +102,11 @@
 
     /**
      * Notify the host application that a page has finished loading. This method
-     * is called only for main frame. When onPageFinished() is called, the
-     * rendering picture may not be updated yet. To get the notification for the
-     * new Picture, use {@link WebView.PictureListener#onNewPicture}.
+     * is called only for main frame. Receiving an {@code onPageFinished()} callback does not
+     * guarantee that the next frame drawn by WebView will reflect the state of the DOM at this
+     * point. In order to be notified that the current DOM state is ready to be rendered, request a
+     * visual state callback with {@link WebView#postVisualStateCallback} and wait for the supplied
+     * callback to be triggered.
      *
      * @param view The WebView that is initiating the callback.
      * @param url The url of the page.
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 4c8f72a..010c0b7 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -238,13 +238,15 @@
 
     public WebViewClient getWebViewClient();
 
-    public WebViewRenderer getWebViewRenderer();
+    @Nullable
+    public WebViewRenderProcess getWebViewRenderProcess();
 
-    public void setWebViewRendererClient(
+    public void setWebViewRenderProcessClient(
             @Nullable Executor executor,
-            @Nullable WebViewRendererClient client);
+            @Nullable WebViewRenderProcessClient client);
 
-    public WebViewRendererClient getWebViewRendererClient();
+    @Nullable
+    public WebViewRenderProcessClient getWebViewRenderProcessClient();
 
     public void setDownloadListener(DownloadListener listener);
 
diff --git a/core/java/android/webkit/WebViewRenderer.java b/core/java/android/webkit/WebViewRenderProcess.java
similarity index 82%
rename from core/java/android/webkit/WebViewRenderer.java
rename to core/java/android/webkit/WebViewRenderProcess.java
index fc38cd9..1be2210 100644
--- a/core/java/android/webkit/WebViewRenderer.java
+++ b/core/java/android/webkit/WebViewRenderProcess.java
@@ -16,12 +16,10 @@
 
 package android.webkit;
 
-import android.annotation.SystemApi;
-
 /**
- * WebViewRenderer provides an opaque handle to a {@link WebView} renderer.
+ * WebViewRenderProcess provides an opaque handle to a {@link WebView} renderer.
  */
-public abstract class WebViewRenderer {
+public abstract class WebViewRenderProcess {
     /**
      * Cause this renderer to terminate.
      *
@@ -38,11 +36,6 @@
      */
     public abstract boolean terminate();
 
-    /**
-     * This class cannot be created by applications.
-     * @hide
-     */
-    @SystemApi
-    public WebViewRenderer() {
+    public WebViewRenderProcess() {
     }
 }
diff --git a/core/java/android/webkit/WebViewRendererClient.java b/core/java/android/webkit/WebViewRenderProcessClient.java
similarity index 66%
rename from core/java/android/webkit/WebViewRendererClient.java
rename to core/java/android/webkit/WebViewRenderProcessClient.java
index 2fadf54..24b8fb5 100644
--- a/core/java/android/webkit/WebViewRendererClient.java
+++ b/core/java/android/webkit/WebViewRenderProcessClient.java
@@ -22,14 +22,14 @@
 /**
  * Used to receive callbacks on {@link WebView} renderer events.
  *
- * WebViewRendererClient instances may be set or retrieved via {@link
- * WebView#setWebViewRendererClient(WebViewRendererClient)} and {@link
- * WebView#getWebViewRendererClient()}.
+ * WebViewRenderProcessClient instances may be set or retrieved via {@link
+ * WebView#setWebViewRenderProcessClient(WebViewRenderProcessClient)} and {@link
+ * WebView#getWebViewRenderProcessClient()}.
  *
  * Instances may be attached to multiple WebViews, and thus a single renderer event may cause
  * a callback to be called multiple times with different WebView parameters.
  */
-public abstract class WebViewRendererClient {
+public abstract class WebViewRenderProcessClient {
     /**
      * Called when the renderer currently associated with {@code view} becomes unresponsive as a
      * result of a long running blocking task such as the execution of JavaScript.
@@ -40,8 +40,11 @@
      *
      * <p>This callback will continue to be called at regular intervals as long as the renderer
      * remains unresponsive. If the renderer becomes responsive again, {@link
-     * WebViewRendererClient#onRendererResponsive} will be called once, and this method will not
-     * subsequently be called unless another period of unresponsiveness is detected.
+     * WebViewRenderProcessClient#onRenderProcessResponsive} will be called once, and this method
+     * will not subsequently be called unless another period of unresponsiveness is detected.
+     *
+     * <p>The minimum interval between successive calls to {@code onRenderProcessUnresponsive} is 5
+     * seconds.
      *
      * <p>No action is taken by WebView as a result of this method call. Applications may
      * choose to terminate the associated renderer via the object that is passed to this callback,
@@ -50,28 +53,28 @@
      * with the same renderer. Failure to do so will result in application termination.
      *
      * @param view The {@link WebView} for which unresponsiveness was detected.
-     * @param renderer The {@link WebViewRenderer} that has become unresponsive,
+     * @param renderer The {@link WebViewRenderProcess} that has become unresponsive,
      * or {@code null} if WebView is running in single process mode.
      */
-    public abstract void onRendererUnresponsive(
-            @NonNull WebView view, @Nullable WebViewRenderer renderer);
+    public abstract void onRenderProcessUnresponsive(
+            @NonNull WebView view, @Nullable WebViewRenderProcess renderer);
 
     /**
      * Called once when an unresponsive renderer currently associated with {@code view} becomes
      * responsive.
      *
      * <p>After a WebView renderer becomes unresponsive, which is notified to the application by
-     * {@link WebViewRendererClient#onRendererUnresponsive}, it is possible for the blocking
-     * renderer task to complete, returning the renderer to a responsive state. In that case,
-     * this method is called once to indicate responsiveness.
+     * {@link WebViewRenderProcessClient#onRenderProcessUnresponsive}, it is possible for the
+     * blocking renderer task to complete, returning the renderer to a responsive state. In that
+     * case, this method is called once to indicate responsiveness.
      *
      * <p>No action is taken by WebView as a result of this method call.
      *
      * @param view The {@link WebView} for which responsiveness was detected.
      *
-     * @param renderer The {@link WebViewRenderer} that has become responsive, or {@code null} if
-     * WebView is running in single process mode.
+     * @param renderer The {@link WebViewRenderProcess} that has become responsive, or {@code null}
+     *                 if WebView is running in single process mode.
      */
-    public abstract void onRendererResponsive(
-            @NonNull WebView view, @Nullable WebViewRenderer renderer);
+    public abstract void onRenderProcessResponsive(
+            @NonNull WebView view, @Nullable WebViewRenderProcess renderer);
 }
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 840cd63..3505994 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3006,8 +3006,6 @@
     <public-group type="dimen" first-id="0x01050007">
         <!-- @hide @SystemApi -->
         <public name="config_restrictedIconSize" />
-        <!-- @hide @SystemApi -->
-        <public name="config_mediaMetadataBitmapMaxSize" />
     </public-group>
 
     <public-group type="color" first-id="0x0106001c">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6671ff8..05cf419 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -280,9 +280,9 @@
     <!-- WFC, summary for Disabled -->
     <string name="wifi_calling_off_summary">Off</string>
     <!-- WFC, summary for Wi-Fi Preferred -->
-    <string name="wfc_mode_wifi_preferred_summary">Wi-Fi preferred</string>
+    <string name="wfc_mode_wifi_preferred_summary">Call over Wi-Fi</string>
     <!-- WFC, summary for Mobile data Preferred -->
-    <string name="wfc_mode_cellular_preferred_summary">Mobile preferred</string>
+    <string name="wfc_mode_cellular_preferred_summary">Call over mobile network</string>
     <!-- WFC, summary for Wi-Fi Only -->
     <string name="wfc_mode_wifi_only_summary">Wi-Fi only</string>
 
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index d4c6eae..6dacc7a 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -81,7 +81,9 @@
     mDevice = VK_NULL_HANDLE;
     mPhysicalDevice = VK_NULL_HANDLE;
     mInstance = VK_NULL_HANDLE;
+    mInstanceExtensionsOwner.clear();
     mInstanceExtensions.clear();
+    mDeviceExtensionsOwner.clear();
     mDeviceExtensions.clear();
     free_features_extensions_structs(mPhysicalDeviceFeatures2);
     mPhysicalDeviceFeatures2 = {};
@@ -106,18 +108,18 @@
         uint32_t extensionCount = 0;
         err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
-        std::unique_ptr<VkExtensionProperties[]> extensions(
-                new VkExtensionProperties[extensionCount]);
-        err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.get());
+        mInstanceExtensionsOwner.resize(extensionCount);
+        err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount,
+                                                    mInstanceExtensionsOwner.data());
         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
         bool hasKHRSurfaceExtension = false;
         bool hasKHRAndroidSurfaceExtension = false;
-        for (uint32_t i = 0; i < extensionCount; ++i) {
-            mInstanceExtensions.push_back(extensions[i].extensionName);
-            if (!strcmp(extensions[i].extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {
+        for (const VkExtensionProperties& extension : mInstanceExtensionsOwner) {
+            mInstanceExtensions.push_back(extension.extensionName);
+            if (!strcmp(extension.extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {
                 hasKHRSurfaceExtension = true;
             }
-            if (!strcmp(extensions[i].extensionName,VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
+            if (!strcmp(extension.extensionName, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
                 hasKHRAndroidSurfaceExtension = true;
             }
         }
@@ -196,15 +198,14 @@
         err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
                 nullptr);
         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
-        std::unique_ptr<VkExtensionProperties[]> extensions(
-                new VkExtensionProperties[extensionCount]);
+        mDeviceExtensionsOwner.resize(extensionCount);
         err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
-                extensions.get());
+                mDeviceExtensionsOwner.data());
         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
         bool hasKHRSwapchainExtension = false;
-        for (uint32_t i = 0; i < extensionCount; ++i) {
-            mDeviceExtensions.push_back(extensions[i].extensionName);
-            if (!strcmp(extensions[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
+        for (const VkExtensionProperties& extension : mDeviceExtensionsOwner) {
+            mDeviceExtensions.push_back(extension.extensionName);
+            if (!strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
                 hasKHRSwapchainExtension = true;
             }
         }
@@ -217,6 +218,7 @@
         }
         return vkGetInstanceProcAddr(instance, proc_name);
     };
+
     grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
             mInstanceExtensions.data(), mDeviceExtensions.size(), mDeviceExtensions.data());
 
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index c3d2891..c2d1802 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -76,6 +76,8 @@
     status_t createReleaseFence(sp<Fence>& nativeFence);
 
     // Returned pointers are owned by VulkanManager.
+    // An instance of VkFunctorInitParams returned from getVkFunctorInitParams refers to
+    // the internal state of VulkanManager: VulkanManager must be alive to use the returned value.
     VkFunctorInitParams getVkFunctorInitParams() const;
 
     sk_sp<GrContext> createContext(const GrContextOptions& options);
@@ -164,7 +166,9 @@
 
     // Variables saved to populate VkFunctorInitParams.
     static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0);
+    std::vector<VkExtensionProperties> mInstanceExtensionsOwner;
     std::vector<const char*> mInstanceExtensions;
+    std::vector<VkExtensionProperties> mDeviceExtensionsOwner;
     std::vector<const char*> mDeviceExtensions;
     VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{};
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 669baea..7783a4d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -553,8 +553,7 @@
      * request is from a hardware key press. (e.g. {@link MediaController}).
      * @hide
      */
-    @SystemApi
-    public static final int FLAG_FROM_KEY = 1 << 16;
+    public static final int FLAG_FROM_KEY = 1 << 12;
 
     // The iterator of TreeMap#entrySet() returns the entries in ascending key order.
     private static final TreeMap<Integer, String> FLAG_NAMES = new TreeMap<>();
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index e0cb86e..c4f8b79 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -166,7 +166,7 @@
             SessionLink sessionLink = manager.createSession(cbLink, tag, sessionInfo);
             mImpl = new MediaSessionEngine(context, sessionLink, cbLink);
             mMaxBitmapSize = context.getResources().getDimensionPixelSize(
-                    android.R.dimen.config_mediaMetadataBitmapMaxSize);
+                    com.android.internal.R.dimen.config_mediaMetadataBitmapMaxSize);
         } catch (RuntimeException e) {
             throw new RuntimeException("Remote error creating session.", e);
         }
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index f210840..190247a 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -14,12 +14,11 @@
 // limitations under the License.
 //
 
-// Library including the network stack, used to compile the network stack app, or linked into the
-// system server on devices that run the stack there
-java_library {
-    name: "NetworkStackLib",
+// Library including the network stack, used to compile both variants of the network stack
+android_library {
+    name: "NetworkStackBase",
     sdk_version: "system_current",
-    installable: true,
+    min_sdk_version: "28",
     srcs: [
         "src/**/*.java",
         ":framework-networkstack-shared-srcs",
@@ -29,7 +28,24 @@
         "netd_aidl_interface-java",
         "networkstack-aidl-interfaces-java",
         "datastallprotosnano",
-    ]
+    ],
+    manifest: "AndroidManifestBase.xml",
+}
+
+// Non-updatable in-process network stack for devices not using the module
+android_app {
+    name: "InProcessNetworkStack",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
+    certificate: "platform",
+    privileged: true,
+    static_libs: [
+        "NetworkStackBase",
+    ],
+    jarjar_rules: "jarjar-rules-shared.txt",
+    // The permission configuration *must* be included to ensure security of the device
+    required: ["NetworkStackPermissionStub"],
+    manifest: "AndroidManifest_InProcess.xml",
 }
 
 // Updatable network stack packaged as an application
@@ -40,9 +56,10 @@
     certificate: "networkstack",
     privileged: true,
     static_libs: [
-        "NetworkStackLib"
+        "NetworkStackBase"
     ],
     jarjar_rules: "jarjar-rules-shared.txt",
-    manifest: "AndroidManifest.xml",
+    // The permission configuration *must* be included to ensure security of the device
     required: ["NetworkStackPermissionStub"],
+    manifest: "AndroidManifest.xml",
 }
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 003f1e5..a90db11 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -18,30 +18,14 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.networkstack"
-          android:sharedUserId="android.uid.networkstack"
-          android:versionCode="11"
-          android:versionName="Q-initial">
-    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+          android:sharedUserId="android.uid.networkstack">
     <!-- Signature permission defined in NetworkStackStub -->
     <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
-    <!-- Send latency broadcast as current user -->
-    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
-    <application
-        android:label="NetworkStack"
-        android:defaultToDeviceProtectedStorage="true"
-        android:directBootAware="true"
-        android:usesCleartextTraffic="true">
+    <application>
         <service android:name="com.android.server.NetworkStackService">
             <intent-filter>
                 <action android:name="android.net.INetworkStackConnector"/>
             </intent-filter>
         </service>
     </application>
-</manifest>
+</manifest>
\ No newline at end of file
diff --git a/packages/NetworkStack/AndroidManifestBase.xml b/packages/NetworkStack/AndroidManifestBase.xml
new file mode 100644
index 0000000..621d30c
--- /dev/null
+++ b/packages/NetworkStack/AndroidManifestBase.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.networkstack"
+          android:versionCode="11"
+          android:versionName="Q-initial">
+    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <!-- Send latency broadcast as current user -->
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+    <application
+        android:label="NetworkStack"
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true"
+        android:usesCleartextTraffic="true">
+    </application>
+</manifest>
diff --git a/packages/NetworkStack/AndroidManifest_InProcess.xml b/packages/NetworkStack/AndroidManifest_InProcess.xml
new file mode 100644
index 0000000..48fcecd
--- /dev/null
+++ b/packages/NetworkStack/AndroidManifest_InProcess.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.networkstack.inprocess"
+          android:sharedUserId="android.uid.system"
+          android:process="system">
+    <application>
+        <service android:name="com.android.server.NetworkStackService" android:process="system">
+            <intent-filter>
+                <action android:name="android.net.INetworkStackConnector.InProcess"/>
+            </intent-filter>
+        </service>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/Android.bp
index e64f284..aadf99e 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/Android.bp
@@ -23,7 +23,7 @@
     static_libs: [
         "androidx.test.rules",
         "mockito-target-extended-minus-junit4",
-        "NetworkStackLib",
+        "NetworkStackBase",
         "testables",
     ],
     libs: [
diff --git a/packages/SettingsLib/res/drawable/ic_smartphone.xml b/packages/SettingsLib/res/drawable/ic_smartphone.xml
new file mode 100644
index 0000000..84a96da
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_smartphone.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:width="24dp"
+        android:height="24dp"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0 0h24v24H0z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M17 1.01L7 1c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h10c1.1 0 2 -0.9 2-2V3c0-1.1 -0.9-1.99-2-1.99zM17 19H7V5h10v14z" />
+</vector>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index c60e8c3..bf97d77 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -937,7 +937,7 @@
     <string name="power_remaining_duration_only_enhanced">About <xliff:g id="time_remaining">%1$s</xliff:g> left based on your usage</string>
     <!-- [CHAR_LIMIT=60] Label for battery level chart when discharging with duration and using enhanced estimate -->
     <string name="power_discharging_duration_enhanced">About <xliff:g id="time_remaining">%1$s</xliff:g> left based on your usage (<xliff:g id="level">%2$s</xliff:g>)</string>
-    <!-- [CHAR_LIMIT=40] Short label for estimated remaining duration of battery charging/discharging -->
+    <!-- [CHAR_LIMIT=20] Short label for estimated remaining duration of battery charging/discharging -->
     <string name="power_remaining_duration_only_short"><xliff:g id="time_remaining">%1$s</xliff:g></string>
 
     <!-- [CHAR_LIMIT=100] Label for enhanced estimated time that phone will run out of battery -->
@@ -948,7 +948,7 @@
     <string name="power_discharge_by">Should last until about <xliff:g id="time">%1$s</xliff:g> (<xliff:g id="level">%2$s</xliff:g>)</string>
     <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
     <string name="power_discharge_by_only">Should last until about <xliff:g id="time">%1$s</xliff:g></string>
-    <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
+    <!-- [CHAR_LIMIT=20] Label for estimated time that phone will run out of battery -->
     <string name="power_discharge_by_only_short">Until <xliff:g id="time" example="12 PM">%1$s</xliff:g></string>
     <!-- [CHAR_LIMIT=100] Extend the battery life past a certain time -->
     <string name="power_suggestion_extend_battery">Extend battery life past <xliff:g id="time" example="12 PM">%1$s</xliff:g></string>
@@ -1153,6 +1153,6 @@
     <!-- The notice header of Third-party licenses. not translatable -->
     <string name="notice_header" translatable="false"></string>
 
-    <!-- Name of the phone device [CHAR LIMIT=NONE] -->
-    <string name="media_transfer_phone_device_name">Phone speaker</string>
+    <!-- Name of the this device. [CHAR LIMIT=30] -->
+    <string name="media_transfer_this_device_name">This device</string>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index 6d0e3ac..3092b99 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -16,6 +16,7 @@
 package com.android.settingslib.media;
 
 import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
 import android.content.Context;
 import android.util.Log;
 
@@ -42,6 +43,11 @@
     }
 
     @Override
+    public String getSummary() {
+        return mCachedDevice.getConnectionSummary();
+    }
+
+    @Override
     public int getIcon() {
         //TODO(b/117129183): This is not final icon for bluetooth device, just for demo.
         return com.android.internal.R.drawable.ic_bt_headphones_a2dp;
@@ -86,4 +92,10 @@
         }
         return false;
     }
+
+    @Override
+    public boolean isConnected() {
+        return mCachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
+                && mCachedDevice.isConnected();
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
index fa2dd88..3a738d2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
@@ -41,6 +41,9 @@
 
     private static final String TAG = "BluetoothMediaManager";
 
+    private final DeviceAttributeChangeCallback mDeviceAttributeChangeCallback =
+            new DeviceAttributeChangeCallback();
+
     private LocalBluetoothManager mLocalBluetoothManager;
     private LocalBluetoothProfileManager mProfileManager;
     private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
@@ -65,7 +68,10 @@
         mLocalBluetoothManager.getEventManager().registerCallback(this);
         buildBluetoothDeviceList();
         dispatchDeviceListAdded();
+        addServiceListenerIfNecessary();
+    }
 
+    private void addServiceListenerIfNecessary() {
         // The profile may not ready when calling startScan().
         // Device status are all disconnected since profiles are not ready to connected.
         // In this case, we observe onServiceConnected() in LocalBluetoothProfileManager.
@@ -78,18 +84,18 @@
 
     private void buildBluetoothDeviceList() {
         mMediaDevices.clear();
-        addConnectedA2dpDevices();
-        addConnectedHearingAidDevices();
+        addConnectableA2dpDevices();
+        addConnectableHearingAidDevices();
     }
 
-    private void addConnectedA2dpDevices() {
+    private void addConnectableA2dpDevices() {
         final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
         if (a2dpProfile == null) {
-            Log.w(TAG, "addConnectedA2dpDevices() a2dp profile is null!");
+            Log.w(TAG, "addConnectableA2dpDevices() a2dp profile is null!");
             return;
         }
 
-        final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
+        final List<BluetoothDevice> devices = a2dpProfile.getConnectableDevices();
 
         for (BluetoothDevice device : devices) {
             final CachedBluetoothDevice cachedDevice =
@@ -100,10 +106,12 @@
                 continue;
             }
 
-            Log.d(TAG, "addConnectedA2dpDevices() device : " + cachedDevice.getName()
-                    + ", is connected : " + cachedDevice.isConnected());
+            Log.d(TAG, "addConnectableA2dpDevices() device : " + cachedDevice.getName()
+                    + ", is connected : " + cachedDevice.isConnected()
+                    + ", is preferred : " + a2dpProfile.isPreferred(device));
 
-            if (cachedDevice.isConnected()) {
+            if (a2dpProfile.isPreferred(device)
+                    && BluetoothDevice.BOND_BONDED == cachedDevice.getBondState()) {
                 addMediaDevice(cachedDevice);
             }
         }
@@ -111,15 +119,15 @@
         mIsA2dpProfileReady = a2dpProfile.isProfileReady();
     }
 
-    private void addConnectedHearingAidDevices() {
+    private void addConnectableHearingAidDevices() {
         final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
         if (hapProfile == null) {
-            Log.w(TAG, "addConnectedA2dpDevices() hap profile is null!");
+            Log.w(TAG, "addConnectableHearingAidDevices() hap profile is null!");
             return;
         }
 
         final List<Long> devicesHiSyncIds = new ArrayList<>();
-        final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
+        final List<BluetoothDevice> devices = hapProfile.getConnectableDevices();
 
         for (BluetoothDevice device : devices) {
             final CachedBluetoothDevice cachedDevice =
@@ -130,13 +138,16 @@
                 continue;
             }
 
-            Log.d(TAG, "addConnectedHearingAidDevices() device : " + cachedDevice.getName()
-                    + ", is connected : " + cachedDevice.isConnected());
+            Log.d(TAG, "addConnectableHearingAidDevices() device : " + cachedDevice.getName()
+                    + ", is connected : " + cachedDevice.isConnected()
+                    + ", is preferred : " + hapProfile.isPreferred(device));
+
             final long hiSyncId = hapProfile.getHiSyncId(device);
 
             // device with same hiSyncId should not be shown in the UI.
             // So do not add it into connectedDevices.
-            if (!devicesHiSyncIds.contains(hiSyncId) && cachedDevice.isConnected()) {
+            if (!devicesHiSyncIds.contains(hiSyncId) && hapProfile.isPreferred(device)
+                    && BluetoothDevice.BOND_BONDED == cachedDevice.getBondState()) {
                 devicesHiSyncIds.add(hiSyncId);
                 addMediaDevice(cachedDevice);
             }
@@ -149,6 +160,7 @@
         MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
         if (mediaDevice == null) {
             mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice);
+            cachedDevice.registerCallback(mDeviceAttributeChangeCallback);
             mLastAddedDevice = mediaDevice;
             mMediaDevices.add(mediaDevice);
         }
@@ -157,6 +169,14 @@
     @Override
     public void stopScan() {
         mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+        unregisterDeviceAttributeChangeCallback();
+    }
+
+    private void unregisterDeviceAttributeChangeCallback() {
+        for (MediaDevice device : mMediaDevices) {
+            ((BluetoothMediaDevice) device).getCachedDevice()
+                    .unregisterCallback(mDeviceAttributeChangeCallback);
+        }
     }
 
     @Override
@@ -164,12 +184,13 @@
         if (BluetoothAdapter.STATE_ON == bluetoothState) {
             buildBluetoothDeviceList();
             dispatchDeviceListAdded();
+            addServiceListenerIfNecessary();
         } else if (BluetoothAdapter.STATE_OFF == bluetoothState) {
             final List<MediaDevice> removeDevicesList = new ArrayList<>();
             for (MediaDevice device : mMediaDevices) {
-                if (device instanceof BluetoothMediaDevice) {
-                    removeDevicesList.add(device);
-                }
+                ((BluetoothMediaDevice) device).getCachedDevice()
+                        .unregisterCallback(mDeviceAttributeChangeCallback);
+                removeDevicesList.add(device);
             }
             mMediaDevices.removeAll(removeDevicesList);
             dispatchDeviceListRemoved(removeDevicesList);
@@ -212,6 +233,7 @@
     private void removeMediaDevice(CachedBluetoothDevice cachedDevice) {
         final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
         if (mediaDevice != null) {
+            cachedDevice.unregisterCallback(mDeviceAttributeChangeCallback);
             mLastRemovedDevice = mediaDevice;
             mMediaDevices.remove(mediaDevice);
         }
@@ -230,12 +252,17 @@
         Log.d(TAG, "onProfileConnectionStateChanged() device: " + cachedDevice
                 + ", state: " + state + ", bluetoothProfile: " + bluetoothProfile);
 
-        if (isCachedDeviceConnected(cachedDevice)) {
-            addMediaDevice(cachedDevice);
-            dispatchDeviceAdded(cachedDevice);
-        } else {
+        updateMediaDeviceListIfNecessary(cachedDevice);
+    }
+
+    private void updateMediaDeviceListIfNecessary(CachedBluetoothDevice cachedDevice) {
+        if (BluetoothDevice.BOND_NONE == cachedDevice.getBondState()) {
             removeMediaDevice(cachedDevice);
             dispatchDeviceRemoved(cachedDevice);
+        } else {
+            if (findMediaDevice(MediaDeviceUtils.getId(cachedDevice)) != null) {
+                dispatchDataChanged();
+            }
         }
     }
 
@@ -243,13 +270,7 @@
     public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
         Log.d(TAG, "onAclConnectionStateChanged() device: " + cachedDevice + ", state: " + state);
 
-        if (isCachedDeviceConnected(cachedDevice)) {
-            addMediaDevice(cachedDevice);
-            dispatchDeviceAdded(cachedDevice);
-        } else {
-            removeMediaDevice(cachedDevice);
-            dispatchDeviceRemoved(cachedDevice);
-        }
+        updateMediaDeviceListIfNecessary(cachedDevice);
     }
 
     @Override
@@ -281,4 +302,16 @@
     public void onServiceDisconnected() {
 
     }
+
+    /**
+     * This callback is for update {@link BluetoothMediaDevice} summary when
+     * {@link CachedBluetoothDevice} connection state is changed.
+     */
+    private class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
+
+        @Override
+        public void onDeviceAttributesChanged() {
+            dispatchDataChanged();
+        }
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 99d9d1c..95f3d3d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -41,6 +41,11 @@
     }
 
     @Override
+    public String getSummary() {
+        return null;
+    }
+
+    @Override
     public int getIcon() {
         //TODO(b/121083246): This is not final icon for cast device, just for demo.
         return com.android.internal.R.drawable.ic_settings_print;
@@ -63,4 +68,9 @@
     public void disconnect() {
         //TODO(b/121083246): disconnected last select device
     }
+
+    @Override
+    public boolean isConnected() {
+        return true;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 44d945a..4e16c66 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -58,7 +58,6 @@
 
     private Context mContext;
     private BluetoothMediaManager mBluetoothMediaManager;
-    private InfoMediaManager mInfoMediaManager;
     private LocalBluetoothManager mLocalBluetoothManager;
 
     @VisibleForTesting
@@ -97,7 +96,6 @@
 
         mBluetoothMediaManager =
                 new BluetoothMediaManager(context, mLocalBluetoothManager, notification);
-        mInfoMediaManager = new InfoMediaManager(context, packageName, notification);
     }
 
     @VisibleForTesting
@@ -106,7 +104,6 @@
         mContext = context;
         mLocalBluetoothManager = localBluetoothManager;
         mBluetoothMediaManager = bluetoothMediaManager;
-        mInfoMediaManager = infoMediaManager;
     }
 
     /**
@@ -115,6 +112,15 @@
      */
     public void connectDevice(MediaDevice connectDevice) {
         final MediaDevice device = getMediaDeviceById(mMediaDevices, connectDevice.getId());
+        if (device instanceof BluetoothMediaDevice) {
+            final CachedBluetoothDevice cachedDevice =
+                    ((BluetoothMediaDevice) device).getCachedDevice();
+            if (!cachedDevice.isConnected() && !cachedDevice.isBusy()) {
+                cachedDevice.connect(true);
+                return;
+            }
+        }
+
         if (device == mCurrentConnectedDevice) {
             Log.d(TAG, "connectDevice() this device all ready connected! : " + device.getName());
             return;
@@ -150,9 +156,7 @@
     public void startScan() {
         mMediaDevices.clear();
         mBluetoothMediaManager.registerCallback(mMediaDeviceCallback);
-        mInfoMediaManager.registerCallback(mMediaDeviceCallback);
         mBluetoothMediaManager.startScan();
-        mInfoMediaManager.startScan();
     }
 
     private void addPhoneDeviceIfNecessary() {
@@ -186,9 +190,7 @@
      */
     public void stopScan() {
         mBluetoothMediaManager.unregisterCallback(mMediaDeviceCallback);
-        mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
         mBluetoothMediaManager.stopScan();
-        mInfoMediaManager.stopScan();
     }
 
     /**
@@ -252,9 +254,17 @@
             }
             addPhoneDeviceIfNecessary();
             mCurrentConnectedDevice = updateCurrentConnectedDevice();
+            updatePhoneMediaDeviceSummary();
             dispatchDeviceListUpdate();
         }
 
+        private void updatePhoneMediaDeviceSummary() {
+            if (mPhoneDevice != null) {
+                ((PhoneMediaDevice) mPhoneDevice)
+                        .updateSummary(mCurrentConnectedDevice == mPhoneDevice);
+            }
+        }
+
         @Override
         public void onDeviceRemoved(MediaDevice device) {
             if (mMediaDevices.contains(device)) {
@@ -272,21 +282,22 @@
         }
 
         @Override
-        public void onDeviceAttributesChanged() {
-            dispatchDeviceListUpdate();
-        }
-
-        @Override
         public void onConnectedDeviceChanged(String id) {
             final MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id);
 
             if (connectDevice == mCurrentConnectedDevice) {
-                Log.d(TAG, "onConnectedDeviceChanged() this device all ready connected! : "
-                        + connectDevice.getName());
+                Log.d(TAG, "onConnectedDeviceChanged() this device all ready connected!");
                 return;
             }
             mCurrentConnectedDevice = connectDevice;
+            updatePhoneMediaDeviceSummary();
+            dispatchDeviceListUpdate();
+        }
 
+        @Override
+        public void onDeviceAttributesChanged() {
+            addPhoneDeviceIfNecessary();
+            removePhoneMediaDeviceIfNecessary();
             dispatchDeviceListUpdate();
         }
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index f35c30e..9b9e803 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -34,9 +34,9 @@
             MediaDeviceType.TYPE_BLUETOOTH_DEVICE,
             MediaDeviceType.TYPE_PHONE_DEVICE})
     public @interface MediaDeviceType {
-        int TYPE_CAST_DEVICE = 1;
-        int TYPE_BLUETOOTH_DEVICE = 2;
-        int TYPE_PHONE_DEVICE = 3;
+        int TYPE_PHONE_DEVICE = 1;
+        int TYPE_CAST_DEVICE = 2;
+        int TYPE_BLUETOOTH_DEVICE = 3;
     }
 
     private int mConnectedRecord;
@@ -63,6 +63,13 @@
     public abstract String getName();
 
     /**
+     * Get summary from MediaDevice.
+     *
+     * @return summary of MediaDevice.
+     */
+    public abstract String getSummary();
+
+    /**
      * Get resource id of MediaDevice.
      *
      * @return resource id of MediaDevice.
@@ -94,6 +101,13 @@
     public abstract void disconnect();
 
     /**
+     * According the MediaDevice type to check whether we are connected to this MediaDevice.
+     *
+     * @return Whether it is connected.
+     */
+    public abstract boolean isConnected();
+
+    /**
      * Rules:
      * 1. If there is one of the connected devices identified as a carkit, this carkit will
      * be always on the top of the device list. Rule 2 and Rule 3 can’t overrule this rule.
@@ -103,9 +117,11 @@
      * 3. For devices with usage record.
      * The most recent used one + device group with usage info sorted by how many times the
      * device has been used.
+     * 4. Phone device always in the top and the connected Bluetooth devices, cast devices and
+     * phone device will be always above on the disconnect Bluetooth devices.
      *
-     * So the device list will look like 4 slots ranked as below.
-     * Rule 1 + the most recently used device + Rule 3 + Rule 2
+     * So the device list will look like 5 slots ranked as below.
+     * Rule 4 + Rule 1 + the most recently used device + Rule 3 + Rule 2
      * Any slot could be empty. And available device will belong to one of the slots.
      *
      * @return a negative integer, zero, or a positive integer
@@ -113,6 +129,21 @@
      */
     @Override
     public int compareTo(MediaDevice another) {
+        // Check Bluetooth device is have same connection state
+        if (isConnected() ^ another.isConnected()) {
+            if (isConnected()) {
+                return -1;
+            } else {
+                return 1;
+            }
+        }
+
+        // Phone device always in the top.
+        if (mType == MediaDeviceType.TYPE_PHONE_DEVICE) {
+            return -1;
+        } else if (another.mType == MediaDeviceType.TYPE_PHONE_DEVICE) {
+            return 1;
+        }
         // Check carkit
         if (isCarKitDevice()) {
             return -1;
@@ -138,7 +169,7 @@
             final String s2 = another.getName();
             return s1.compareToIgnoreCase(s2);
         }
-        // Both devices have never been used, the priority is Cast > Bluetooth > Phone
+        // Both devices have never been used, the priority is Phone > Cast > Bluetooth
         return mType - another.mType;
     }
 
@@ -149,4 +180,13 @@
     protected boolean isCarKitDevice() {
         return false;
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof MediaDevice)) {
+            return false;
+        }
+        final MediaDevice otherDevice = (MediaDevice) obj;
+        return otherDevice.getId().equals(getId());
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
index 2c3a96c..7898982 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
@@ -117,6 +117,14 @@
         }
     }
 
+    protected void dispatchDataChanged() {
+        synchronized (mCallbacks) {
+            for (MediaDeviceCallback callback : mCallbacks) {
+                callback.onDeviceAttributesChanged();
+            }
+        }
+    }
+
     /**
      * Callback for notifying device is added, removed and attributes changed.
      */
@@ -150,15 +158,16 @@
         void onDeviceListRemoved(List<MediaDevice> devices);
 
         /**
-         * Callback for notifying MediaDevice attributes is changed.
-         */
-        void onDeviceAttributesChanged();
-
-        /**
          * Callback for notifying connected MediaDevice is changed.
          *
          * @param id the id of MediaDevice
          */
         void onConnectedDeviceChanged(String id);
+
+        /**
+         * Callback for notifying that MediaDevice attributes
+         * (e.g: device name, connection state, subtitle) is changed.
+         */
+        void onDeviceAttributesChanged();
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index 8ec2a7f..da140aa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.util.Log;
 
+import com.android.settingslib.R;
 import com.android.settingslib.bluetooth.A2dpProfile;
 import com.android.settingslib.bluetooth.HearingAidProfile;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -34,6 +35,7 @@
 
     private LocalBluetoothProfileManager mProfileManager;
     private LocalBluetoothManager mLocalBluetoothManager;
+    private String mSummary = "";
 
     PhoneMediaDevice(Context context, LocalBluetoothManager localBluetoothManager) {
         super(context, MediaDeviceType.TYPE_PHONE_DEVICE);
@@ -45,14 +47,17 @@
 
     @Override
     public String getName() {
-        return mContext
-                .getString(com.android.settingslib.R.string.media_transfer_phone_device_name);
+        return mContext.getString(R.string.media_transfer_this_device_name);
+    }
+
+    @Override
+    public String getSummary() {
+        return mSummary;
     }
 
     @Override
     public int getIcon() {
-        //TODO(b/117129183): This is not final icon for phone device, just for demo.
-        return com.android.internal.R.drawable.ic_phone;
+        return R.drawable.ic_smartphone;
     }
 
     @Override
@@ -69,6 +74,7 @@
 
         if (hapProfile != null && a2dpProfile != null) {
             isConnected = hapProfile.setActiveDevice(null) && a2dpProfile.setActiveDevice(null);
+            updateSummary(true);
             setConnectedRecord();
         }
         Log.d(TAG, "connect() device : " + getName() + ", is selected : " + isConnected);
@@ -77,6 +83,20 @@
 
     @Override
     public void disconnect() {
-        //TODO(b/117129183): disconnected last select device
+        updateSummary(false);
+    }
+
+    @Override
+    public boolean isConnected() {
+        return true;
+    }
+
+    /**
+     * According current active device is {@link PhoneMediaDevice} or not to update summary.
+     */
+    public void updateSummary(boolean isActive) {
+        mSummary = isActive
+                ? mContext.getString(R.string.bluetooth_active_no_battery_level)
+                : "";
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index 5600dd2..7046d23 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -223,12 +223,19 @@
     }
 
     private static String getRegularTimeRemainingShortString(Context context, long drainTimeMs) {
-        // Get the time remaining rounded to the nearest 15 min
-        final long roundedTimeMs = roundTimeToNearestThreshold(drainTimeMs, FIFTEEN_MINUTES_MILLIS);
-        CharSequence timeString = StringUtil.formatElapsedTime(context, roundedTimeMs,
-                false /* withSeconds */);
+        // Get the time of day we think device will die rounded to the nearest 15 min.
+        final long roundedTimeOfDayMs =
+                roundTimeToNearestThreshold(
+                        System.currentTimeMillis() + drainTimeMs,
+                        FIFTEEN_MINUTES_MILLIS);
 
-        return context.getString(R.string.power_remaining_duration_only_short, timeString);
+        // convert the time to a properly formatted string.
+        String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
+        DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
+        Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs));
+        CharSequence timeString = fmt.format(date);
+
+        return context.getString(R.string.power_discharge_by_only_short, timeString);
     }
 
     public static long convertUsToMs(long timeUs) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index d9b4885..59fbb72 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1076,7 +1076,7 @@
             return (info.isOsuAp() && mOsuStatus != null);
         } else if (info.isPasspointAp() || isPasspoint()) {
             return (info.isPasspointAp() && isPasspoint()
-                    && TextUtils.equals(info.getFqdn(), mConfig.FQDN));
+                    && TextUtils.equals(info.getPasspointFqdn(), mConfig.FQDN));
         }
 
         if (networkId != WifiConfiguration.INVALID_NETWORK_ID) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 3c10688..2ab369c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -118,7 +118,7 @@
                 mWifiInfo = mWifiManager.getConnectionInfo();
                 if (mWifiInfo != null) {
                     if (mWifiInfo.isPasspointAp() || mWifiInfo.isOsuAp()) {
-                        ssid = mWifiInfo.getProviderFriendlyName();
+                        ssid = mWifiInfo.getPasspointProviderFriendlyName();
                     } else {
                         ssid = getValidSsid(mWifiInfo);
                     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java
index e5d1b18..e0e2fd6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java
@@ -20,6 +20,7 @@
 
 import static org.mockito.Mockito.when;
 
+import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 
@@ -66,4 +67,20 @@
 
         assertThat(mBluetoothMediaDevice.connect()).isFalse();
     }
+
+    @Test
+    public void isCachedBluetoothDeviceConnected_deviceConnected_returnTrue() {
+        when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice.isConnected()).thenReturn(true);
+
+        assertThat(mBluetoothMediaDevice.isConnected()).isTrue();
+    }
+
+    @Test
+    public void isCachedBluetoothDeviceConnected_deviceNotConnected_returnFalse() {
+        when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice.isConnected()).thenReturn(false);
+
+        assertThat(mBluetoothMediaDevice.isConnected()).isFalse();
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java
index a20e22b..48449f2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java
@@ -87,15 +87,16 @@
     }
 
     @Test
-    public void startScan_haveA2dpProfileConnectedBluetoothDevice_shouldAddDevice() {
+    public void startScan_haveA2dpProfileDeviceIsPreferredAndBonded_shouldAddDevice() {
         final List<BluetoothDevice> devices = new ArrayList<>();
         final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
         final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
         devices.add(bluetoothDevice);
 
-        when(mA2dpProfile.getConnectedDevices()).thenReturn(devices);
+        when(mA2dpProfile.getConnectableDevices()).thenReturn(devices);
         when(mCachedDeviceManager.findDevice(bluetoothDevice)).thenReturn(cachedDevice);
-        when(cachedDevice.isConnected()).thenReturn(true);
+        when(cachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mA2dpProfile.isPreferred(bluetoothDevice)).thenReturn(true);
 
         assertThat(mMediaManager.mMediaDevices).isEmpty();
         mMediaManager.startScan();
@@ -103,15 +104,16 @@
     }
 
     @Test
-    public void startScan_haveA2dpProfileDisconnectedBluetoothDevice_shouldNotAddDevice() {
+    public void startScan_haveA2dpProfileDeviceIsPreferredAndBondNone_shouldNotAddDevice() {
         final List<BluetoothDevice> devices = new ArrayList<>();
         final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
         final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
         devices.add(bluetoothDevice);
 
-        when(mA2dpProfile.getConnectedDevices()).thenReturn(devices);
+        when(mA2dpProfile.getConnectableDevices()).thenReturn(devices);
         when(mCachedDeviceManager.findDevice(bluetoothDevice)).thenReturn(cachedDevice);
-        when(cachedDevice.isConnected()).thenReturn(false);
+        when(cachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        when(mA2dpProfile.isPreferred(bluetoothDevice)).thenReturn(true);
 
         assertThat(mMediaManager.mMediaDevices).isEmpty();
         mMediaManager.startScan();
@@ -122,7 +124,7 @@
     public void startScan_noA2dpProfileBluetoothDevice_shouldNotAddDevice() {
         final List<BluetoothDevice> devices = new ArrayList<>();
 
-        when(mA2dpProfile.getConnectedDevices()).thenReturn(devices);
+        when(mA2dpProfile.getConnectableDevices()).thenReturn(devices);
 
         assertThat(mMediaManager.mMediaDevices).isEmpty();
         mMediaManager.startScan();
@@ -130,15 +132,16 @@
     }
 
     @Test
-    public void startScan_haveHapProfileConnectedBluetoothDevice_shouldAddDevice() {
+    public void startScan_haveHapProfileDeviceIsPreferredAndBonded_shouldAddDevice() {
         final List<BluetoothDevice> devices = new ArrayList<>();
         final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
         final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
         devices.add(bluetoothDevice);
 
-        when(mHapProfile.getConnectedDevices()).thenReturn(devices);
+        when(mHapProfile.getConnectableDevices()).thenReturn(devices);
         when(mCachedDeviceManager.findDevice(bluetoothDevice)).thenReturn(cachedDevice);
-        when(cachedDevice.isConnected()).thenReturn(true);
+        when(cachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mHapProfile.isPreferred(bluetoothDevice)).thenReturn(true);
 
         assertThat(mMediaManager.mMediaDevices).isEmpty();
         mMediaManager.startScan();
@@ -149,7 +152,7 @@
     public void startScan_noHapProfileBluetoothDevice_shouldNotAddDevice() {
         final List<BluetoothDevice> devices = new ArrayList<>();
 
-        when(mHapProfile.getConnectedDevices()).thenReturn(devices);
+        when(mHapProfile.getConnectableDevices()).thenReturn(devices);
 
         assertThat(mMediaManager.mMediaDevices).isEmpty();
         mMediaManager.startScan();
@@ -230,9 +233,14 @@
     public void onBluetoothStateChanged_bluetoothStateIsOff_callOnDeviceListRemoved() {
         final BluetoothMediaDevice device1 = mock(BluetoothMediaDevice.class);
         final BluetoothMediaDevice device2 = mock(BluetoothMediaDevice.class);
+        final CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
+        final CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class);
         mMediaManager.mMediaDevices.add(device1);
         mMediaManager.mMediaDevices.add(device2);
 
+        when(device1.getCachedDevice()).thenReturn(cachedDevice1);
+        when(device2.getCachedDevice()).thenReturn(cachedDevice2);
+
         mMediaManager.registerCallback(mCallback);
         mMediaManager.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
 
@@ -311,28 +319,30 @@
     }
 
     @Test
-    public void onProfileConnectionStateChanged_cachedDeviceIsConnect_callOnDeviceAdded() {
-        final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
-
-        when(device.isConnectedHearingAidDevice()).thenReturn(true);
-        when(device.isConnectedA2dpDevice()).thenReturn(true);
-
-        assertThat(mMediaManager.mMediaDevices).isEmpty();
-        mMediaManager.registerCallback(mCallback);
-        mMediaManager.onProfileConnectionStateChanged(device, 0, 0);
-
-        assertThat(mMediaManager.mMediaDevices).hasSize(1);
-        verify(mCallback).onDeviceAdded(any());
-    }
-
-    @Test
-    public void onProfileConnectionStateChanged_cachedDeviceIsDisconnect_callOnDeviceRemoved() {
+    public void onProfileConnectionStateChanged_cachedDeviceIsBonded_callDeviceAttributesChanged() {
         final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
         final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
         mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
 
-        when(device.isConnectedHearingAidDevice()).thenReturn(false);
-        when(device.isConnectedA2dpDevice()).thenReturn(false);
+        when(device.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(device.getAddress()).thenReturn(TEST_ADDRESS);
+        when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
+
+        assertThat(mMediaManager.mMediaDevices).hasSize(1);
+        mMediaManager.registerCallback(mCallback);
+        mMediaManager.onProfileConnectionStateChanged(device, 0, 0);
+
+        assertThat(mMediaManager.mMediaDevices).hasSize(1);
+        verify(mCallback).onDeviceAttributesChanged();
+    }
+
+    @Test
+    public void onProfileConnectionStateChanged_cachedDeviceIsBondNone_callOnDeviceRemoved() {
+        final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
+        final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
+        mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
+
+        when(device.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
         when(device.getAddress()).thenReturn(TEST_ADDRESS);
         when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
 
@@ -345,28 +355,30 @@
     }
 
     @Test
-    public void onAclConnectionStateChanged_cachedDeviceIsConnect_callOnDeviceAdded() {
-        final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
-
-        when(device.isConnectedHearingAidDevice()).thenReturn(true);
-        when(device.isConnectedA2dpDevice()).thenReturn(true);
-
-        assertThat(mMediaManager.mMediaDevices).isEmpty();
-        mMediaManager.registerCallback(mCallback);
-        mMediaManager.onAclConnectionStateChanged(device, 0);
-
-        assertThat(mMediaManager.mMediaDevices).hasSize(1);
-        verify(mCallback).onDeviceAdded(any());
-    }
-
-    @Test
-    public void onAclConnectionStateChanged_cachedDeviceIsDisconnect_callOnDeviceRemoved() {
+    public void onAclConnectionStateChanged_cachedDeviceIsBonded_callDeviceAttributesChanged() {
         final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
         final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
         mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
 
-        when(device.isConnectedHearingAidDevice()).thenReturn(false);
-        when(device.isConnectedA2dpDevice()).thenReturn(false);
+        when(device.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(device.getAddress()).thenReturn(TEST_ADDRESS);
+        when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
+
+        assertThat(mMediaManager.mMediaDevices).hasSize(1);
+        mMediaManager.registerCallback(mCallback);
+        mMediaManager.onAclConnectionStateChanged(device, 0);
+
+        assertThat(mMediaManager.mMediaDevices).hasSize(1);
+        verify(mCallback).onDeviceAttributesChanged();
+    }
+
+    @Test
+    public void onAclConnectionStateChanged_cachedDeviceIsBondNone_callOnDeviceRemoved() {
+        final CachedBluetoothDevice device = mock(CachedBluetoothDevice.class);
+        final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class);
+        mMediaManager.mMediaDevices.add(bluetoothMediaDevice);
+
+        when(device.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
         when(device.getAddress()).thenReturn(TEST_ADDRESS);
         when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS);
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index 3556814..98bb74a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 
 import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.HearingAidProfile;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
@@ -113,6 +114,23 @@
     }
 
     @Test
+    public void connectDevice_bluetoothDeviceNotConnected_connectBluetoothDevice() {
+        final MediaDevice device = mock(BluetoothMediaDevice.class);
+        final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
+        mLocalMediaManager.mMediaDevices.add(device);
+
+        when(device.getId()).thenReturn(TEST_DEVICE_ID_1);
+        when(((BluetoothMediaDevice) device).getCachedDevice()).thenReturn(cachedDevice);
+        when(cachedDevice.isConnected()).thenReturn(false);
+        when(cachedDevice.isBusy()).thenReturn(false);
+
+        mLocalMediaManager.registerCallback(mCallback);
+        mLocalMediaManager.connectDevice(device);
+
+        verify(cachedDevice).connect(true);
+    }
+
+    @Test
     public void getMediaDeviceById_idExist_shouldReturnMediaDevice() {
         final MediaDevice device1 = mock(MediaDevice.class);
         final MediaDevice device2 = mock(MediaDevice.class);
@@ -322,15 +340,6 @@
     }
 
     @Test
-    public void onDeviceAttributesChanged_shouldDispatchDeviceListUpdate() {
-        mLocalMediaManager.registerCallback(mCallback);
-
-        mLocalMediaManager.mMediaDeviceCallback.onDeviceAttributesChanged();
-
-        verify(mCallback).onDeviceListUpdate(any());
-    }
-
-    @Test
     public void onConnectedDeviceChanged_connectedAndCurrentDeviceAreDifferent_notifyThemChanged() {
         final MediaDevice device1 = mock(MediaDevice.class);
         final MediaDevice device2 = mock(MediaDevice.class);
@@ -366,4 +375,13 @@
 
         verify(mCallback, never()).onDeviceListUpdate(any());
     }
+
+    @Test
+    public void onDeviceAttributesChanged_shouldDispatchDeviceListUpdate() {
+        mLocalMediaManager.registerCallback(mCallback);
+
+        mLocalMediaManager.mMediaDeviceCallback.onDeviceAttributesChanged();
+
+        verify(mCallback).onDeviceListUpdate(any());
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index fc514f0..23d2c74 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -114,6 +114,12 @@
         when(mCachedDevice1.getDevice()).thenReturn(mDevice1);
         when(mCachedDevice2.getDevice()).thenReturn(mDevice2);
         when(mCachedDevice3.getDevice()).thenReturn(mDevice3);
+        when(mCachedDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mCachedDevice1.isConnected()).thenReturn(true);
+        when(mCachedDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mCachedDevice2.isConnected()).thenReturn(true);
+        when(mCachedDevice3.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mCachedDevice3.isConnected()).thenReturn(true);
         when(mRouteInfo1.getId()).thenReturn(ROUTER_ID_1);
         when(mRouteInfo2.getId()).thenReturn(ROUTER_ID_2);
         when(mRouteInfo3.getId()).thenReturn(ROUTER_ID_3);
@@ -158,12 +164,25 @@
     }
 
     @Test
-    public void compareTo_carKit_phone_carKitFirst() {
+    public void compareTo_carKit_phone_phoneFirst() {
         when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
-        mMediaDevices.add(mPhoneMediaDevice);
         mMediaDevices.add(mBluetoothMediaDevice1);
+        mMediaDevices.add(mPhoneMediaDevice);
 
+        assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+        Collections.sort(mMediaDevices, COMPARATOR);
         assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
+    }
+
+    @Test
+    public void compareTo_carKitIsDisConnected_nonCarKitBluetooth_nonCarKitBluetoothFirst() {
+        when(mDevice1.getBluetoothClass()).thenReturn(mHeadreeClass);
+        when(mDevice2.getBluetoothClass()).thenReturn(mCarkitClass);
+        when(mCachedDevice2.isConnected()).thenReturn(false);
+        mMediaDevices.add(mBluetoothMediaDevice1);
+        mMediaDevices.add(mBluetoothMediaDevice2);
+
+        assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
         Collections.sort(mMediaDevices, COMPARATOR);
         assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
     }
@@ -178,6 +197,7 @@
         Collections.sort(mMediaDevices, COMPARATOR);
         assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
     }
+
     @Test
     public void compareTo_connectionRecord_sortByRecord() {
         mMediaDevices.add(mBluetoothMediaDevice1);
@@ -196,6 +216,25 @@
     }
 
     @Test
+    public void compareTo_sortByRecord_connectedDeviceFirst() {
+        mMediaDevices.add(mBluetoothMediaDevice1);
+        mMediaDevices.add(mBluetoothMediaDevice2);
+        when(mCachedDevice2.isConnected()).thenReturn(false);
+
+        mBluetoothMediaDevice1.connect();
+        mBluetoothMediaDevice2.connect();
+        mBluetoothMediaDevice2.connect();
+        // Reset last selected record
+        ConnectionRecordManager.getInstance().setConnectionRecord(mContext, null, 0);
+
+        assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+        assertThat(mMediaDevices.get(1)).isEqualTo(mBluetoothMediaDevice2);
+        Collections.sort(mMediaDevices, COMPARATOR);
+        assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+        assertThat(mMediaDevices.get(1)).isEqualTo(mBluetoothMediaDevice2);
+    }
+
+    @Test
     public void compareTo_info_bluetooth_infoFirst() {
         mMediaDevices.add(mBluetoothMediaDevice1);
         mMediaDevices.add(mInfoMediaDevice1);
@@ -206,13 +245,13 @@
     }
 
     @Test
-    public void compareTo_bluetooth_phone_bluetoothFirst() {
-        mMediaDevices.add(mPhoneMediaDevice);
+    public void compareTo_bluetooth_phone_phoneFirst() {
         mMediaDevices.add(mBluetoothMediaDevice1);
+        mMediaDevices.add(mPhoneMediaDevice);
 
-        assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
-        Collections.sort(mMediaDevices, COMPARATOR);
         assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+        Collections.sort(mMediaDevices, COMPARATOR);
+        assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
     }
 
     @Test
@@ -235,6 +274,17 @@
         assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
     }
 
+    @Test
+    public void compareTo_sortByAlphabet_connectDeviceFirst() {
+        mMediaDevices.add(mBluetoothMediaDevice2);
+        mMediaDevices.add(mBluetoothMediaDevice1);
+        when(mCachedDevice1.isConnected()).thenReturn(false);
+
+        assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
+        Collections.sort(mMediaDevices, COMPARATOR);
+        assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice2);
+    }
+
     // 1.mInfoMediaDevice1:      Last Selected device
     // 2.mBluetoothMediaDevice1: CarKit device
     // 3.mInfoMediaDevice2:      * 2 times usage
@@ -242,7 +292,7 @@
     // 5.mBluetoothMediaDevice2: * 2 times usage
     // 6.mBluetoothMediaDevice3: * 1 time usage
     // 7.mPhoneMediaDevice:      * 0 time usage
-    // Order: 2 -> 1 -> 3 -> 5 -> 4 -> 6 -> 7
+    // Order: 7 -> 2 -> 1 -> 3 -> 5 -> 4 -> 6
     @Test
     public void compareTo_mixedDevices_carKitFirst() {
         when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
@@ -264,13 +314,55 @@
         mInfoMediaDevice1.connect();
 
         Collections.sort(mMediaDevices, COMPARATOR);
-        assertThat(mMediaDevices.get(0)).isEqualTo(mBluetoothMediaDevice1);
+        assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
+        assertThat(mMediaDevices.get(1)).isEqualTo(mBluetoothMediaDevice1);
+        assertThat(mMediaDevices.get(2)).isEqualTo(mInfoMediaDevice1);
+        assertThat(mMediaDevices.get(3)).isEqualTo(mInfoMediaDevice2);
+        assertThat(mMediaDevices.get(4)).isEqualTo(mBluetoothMediaDevice2);
+        assertThat(mMediaDevices.get(5)).isEqualTo(mInfoMediaDevice3);
+        assertThat(mMediaDevices.get(6)).isEqualTo(mBluetoothMediaDevice3);
+    }
+
+    // 1.mInfoMediaDevice1:      Last Selected device
+    // 2.mBluetoothMediaDevice1: CarKit device not connected
+    // 3.mInfoMediaDevice2:      * 2 times usage
+    // 4.mInfoMediaDevice3:      * 1 time usage
+    // 5.mBluetoothMediaDevice2: * 4 times usage not connected
+    // 6.mBluetoothMediaDevice3: * 1 time usage
+    // 7.mPhoneMediaDevice:      * 0 time usage
+    // Order: 7 -> 1 -> 3 -> 4 -> 6 -> 2 -> 5
+    @Test
+    public void compareTo_mixedDevices_connectDeviceFirst() {
+        when(mDevice1.getBluetoothClass()).thenReturn(mCarkitClass);
+        when(mDevice2.getBluetoothClass()).thenReturn(mHeadreeClass);
+        when(mDevice3.getBluetoothClass()).thenReturn(mHeadreeClass);
+        when(mCachedDevice1.isConnected()).thenReturn(false);
+        when(mCachedDevice2.isConnected()).thenReturn(false);
+        mMediaDevices.add(mBluetoothMediaDevice1);
+        mMediaDevices.add(mBluetoothMediaDevice2);
+        mMediaDevices.add(mBluetoothMediaDevice3);
+        mMediaDevices.add(mInfoMediaDevice1);
+        mMediaDevices.add(mInfoMediaDevice2);
+        mMediaDevices.add(mInfoMediaDevice3);
+        mMediaDevices.add(mPhoneMediaDevice);
+        mBluetoothMediaDevice3.connect();
+        mBluetoothMediaDevice2.connect();
+        mBluetoothMediaDevice2.connect();
+        mBluetoothMediaDevice2.connect();
+        mBluetoothMediaDevice2.connect();
+        mInfoMediaDevice3.connect();
+        mInfoMediaDevice2.connect();
+        mInfoMediaDevice2.connect();
+        mInfoMediaDevice1.connect();
+
+        Collections.sort(mMediaDevices, COMPARATOR);
+        assertThat(mMediaDevices.get(0)).isEqualTo(mPhoneMediaDevice);
         assertThat(mMediaDevices.get(1)).isEqualTo(mInfoMediaDevice1);
         assertThat(mMediaDevices.get(2)).isEqualTo(mInfoMediaDevice2);
-        assertThat(mMediaDevices.get(3)).isEqualTo(mBluetoothMediaDevice2);
-        assertThat(mMediaDevices.get(4)).isEqualTo(mInfoMediaDevice3);
-        assertThat(mMediaDevices.get(5)).isEqualTo(mBluetoothMediaDevice3);
-        assertThat(mMediaDevices.get(6)).isEqualTo(mPhoneMediaDevice);
+        assertThat(mMediaDevices.get(3)).isEqualTo(mInfoMediaDevice3);
+        assertThat(mMediaDevices.get(4)).isEqualTo(mBluetoothMediaDevice3);
+        assertThat(mMediaDevices.get(5)).isEqualTo(mBluetoothMediaDevice1);
+        assertThat(mMediaDevices.get(6)).isEqualTo(mBluetoothMediaDevice2);
     }
 
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java
index 98eccb5..ead2be4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java
@@ -111,6 +111,15 @@
     }
 
     @Test
+    public void dispatchDataChanged_registerCallback_shouldDispatchCallback() {
+        mMediaManager.registerCallback(mCallback);
+
+        mMediaManager.dispatchDataChanged();
+
+        verify(mCallback).onDeviceAttributesChanged();
+    }
+
+    @Test
     public void findMediaDevice_idExist_shouldReturnMediaDevice() {
         mMediaManager.mMediaDevices.add(mDevice);
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
index 5ba33f5..50a6a9d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
@@ -23,6 +23,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
 
+import com.android.settingslib.R;
 import com.android.settingslib.bluetooth.A2dpProfile;
 import com.android.settingslib.bluetooth.HearingAidProfile;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -97,4 +98,19 @@
 
         assertThat(mPhoneMediaDevice.connect()).isFalse();
     }
+
+    @Test
+    public void updateSummary_isActiveIsTrue_returnActiveString() {
+        mPhoneMediaDevice.updateSummary(true);
+
+        assertThat(mPhoneMediaDevice.getSummary())
+                .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level));
+    }
+
+    @Test
+    public void updateSummary_notActive_returnEmpty() {
+        mPhoneMediaDevice.updateSummary(false);
+
+        assertThat(mPhoneMediaDevice.getSummary()).isEmpty();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index 7cbe1a3..059c3f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -22,10 +22,12 @@
 import android.app.NotificationManager;
 import android.content.Context;
 import android.database.ContentObserver;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
@@ -54,6 +56,7 @@
     private final StatusBarStateController mStatusBarStateController =
             Dependency.get(StatusBarStateController.class);
     private final NotificationFilter mNotificationFilter = Dependency.get(NotificationFilter.class);
+    private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
 
     private final Context mContext;
     private final PowerManager mPowerManager;
@@ -73,17 +76,20 @@
         this(context,
                 (PowerManager) context.getSystemService(Context.POWER_SERVICE),
                 IDreamManager.Stub.asInterface(
-                        ServiceManager.checkService(DreamService.DREAM_SERVICE)));
+                        ServiceManager.checkService(DreamService.DREAM_SERVICE)),
+                new AmbientDisplayConfiguration(context));
     }
 
     @VisibleForTesting
     protected NotificationInterruptionStateProvider(
             Context context,
             PowerManager powerManager,
-            IDreamManager dreamManager) {
+            IDreamManager dreamManager,
+            AmbientDisplayConfiguration ambientDisplayConfiguration) {
         mContext = context;
         mPowerManager = powerManager;
         mDreamManager = dreamManager;
+        mAmbientDisplayConfiguration = ambientDisplayConfiguration;
     }
 
     /** Sets up late-binding dependencies for this component. */
@@ -232,6 +238,13 @@
     public boolean shouldPulse(NotificationEntry entry) {
         StatusBarNotification sbn = entry.notification;
 
+        if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) {
+            if (DEBUG) {
+                Log.d(TAG, "No pulsing: disabled by setting: " + sbn.getKey());
+            }
+            return false;
+        }
+
         if (!getShadeController().isDozing()) {
             if (DEBUG) {
                 Log.d(TAG, "No pulsing: not dozing: " + sbn.getKey());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 265fa2c..1949bad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -90,6 +90,10 @@
      */
     public static final float GRADIENT_SCRIM_ALPHA = 0.2f;
     /**
+     * Scrim opacity when the phone is about to wake-up.
+     */
+    public static final float AOD2_SCRIM_ALPHA = 0.6f;
+    /**
      * A scrim varies its opacity based on a busyness factor, for example
      * how many notifications are currently visible.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index ccf5e4e..2f161d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -133,11 +133,10 @@
                     || mPulseReason == DozeLog.PULSE_REASON_DOCKING
                     || mPulseReason == DozeLog.PULSE_REASON_INTENT) {
                 mCurrentBehindAlpha = previousState.getBehindAlpha();
-                mCurrentBehindTint = Color.BLACK;
             } else {
-                mCurrentBehindAlpha = mScrimBehindAlphaKeyguard;
-                mCurrentBehindTint = Color.TRANSPARENT;
+                mCurrentBehindAlpha = ScrimController.AOD2_SCRIM_ALPHA;
             }
+            mCurrentBehindTint = Color.BLACK;
             mBlankScreen = mDisplayRequiresBlanking;
         }
     },
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 7e5c3db..539851f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -232,7 +232,7 @@
         // Back scrim should be semi-transparent so the user can see the wallpaper
         // Pulse callback should have been invoked
         assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
-        assertScrimTint(mScrimBehind, false /* tinted */);
+        assertScrimTint(mScrimBehind, true /* tinted */);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index cbbee39..1ded6c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -41,6 +41,7 @@
 import android.app.StatusBarManager;
 import android.app.trust.TrustManager;
 import android.content.Context;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.hardware.fingerprint.FingerprintManager;
 import android.metrics.LogMaker;
 import android.os.Binder;
@@ -169,6 +170,8 @@
     private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
     @Mock
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Mock
+    private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
 
     private TestableStatusBar mStatusBar;
     private FakeMetricsLogger mMetricsLogger;
@@ -205,7 +208,7 @@
 
         mNotificationInterruptionStateProvider =
                 new TestableNotificationInterruptionStateProvider(mContext, mPowerManager,
-                        mDreamManager);
+                        mDreamManager, mAmbientDisplayConfiguration);
         mDependency.injectTestDependency(NotificationInterruptionStateProvider.class,
                 mNotificationInterruptionStateProvider);
         mDependency.injectMockDependency(NavigationBarController.class);
@@ -832,8 +835,9 @@
         public TestableNotificationInterruptionStateProvider(
                 Context context,
                 PowerManager powerManager,
-                IDreamManager dreamManager) {
-            super(context, powerManager, dreamManager);
+                IDreamManager dreamManager,
+                AmbientDisplayConfiguration ambientDisplayConfiguration) {
+            super(context, powerManager, dreamManager, ambientDisplayConfiguration);
             mUseHeadsUp = true;
         }
     }
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index 58dbea4..69b4672 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -32,6 +32,7 @@
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.Slog;
 
 import com.android.server.LocalServices;
@@ -63,7 +64,8 @@
 
     public ContentSuggestionsManagerService(Context context) {
         super(context, new FrameworkResourcesServiceNameResolver(context,
-                com.android.internal.R.string.config_defaultContentSuggestionsService), null);
+                com.android.internal.R.string.config_defaultContentSuggestionsService),
+                UserManager.DISALLOW_CONTENT_SUGGESTIONS);
         mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 85322d6..57ce98c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1674,8 +1674,9 @@
 
     int runSwitchUser(PrintWriter pw) throws RemoteException {
         UserManager userManager = mInternal.mContext.getSystemService(UserManager.class);
-        if (!userManager.canSwitchUsers()) {
-            getErrPrintWriter().println("Error: disallowed switching user");
+        final int userSwitchable = userManager.getUserSwitchability();
+        if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
+            getErrPrintWriter().println("Error: " + userSwitchable);
             return -1;
         }
         String user = getNextArgRequired();
diff --git a/services/core/java/com/android/server/am/BroadcastDispatcher.java b/services/core/java/com/android/server/am/BroadcastDispatcher.java
index b0b1840..d029482 100644
--- a/services/core/java/com/android/server/am/BroadcastDispatcher.java
+++ b/services/core/java/com/android/server/am/BroadcastDispatcher.java
@@ -450,6 +450,8 @@
             return mCurrentBroadcast;
         }
 
+        final boolean someQueued = !mOrderedBroadcasts.isEmpty();
+
         BroadcastRecord next = null;
         if (!mAlarmBroadcasts.isEmpty()) {
             next = popLocked(mAlarmBroadcasts);
@@ -459,10 +461,18 @@
         }
 
         if (next == null && !mDeferredBroadcasts.isEmpty()) {
+            // We're going to deliver either:
+            // 1. the next "overdue" deferral; or
+            // 2. the next ordinary ordered broadcast; *or*
+            // 3. the next not-yet-overdue deferral.
+
             for (int i = 0; i < mDeferredBroadcasts.size(); i++) {
                 Deferrals d = mDeferredBroadcasts.get(i);
-                if (now < d.deferUntil) {
-                    // No more deferrals due
+                if (now < d.deferUntil && someQueued) {
+                    // stop looking when we haven't hit the next time-out boundary
+                    // but only if we have un-deferred broadcasts waiting,
+                    // otherwise we can deliver whatever deferred broadcast
+                    // is next available.
                     break;
                 }
 
@@ -483,7 +493,7 @@
             }
         }
 
-        if (next == null && !mOrderedBroadcasts.isEmpty()) {
+        if (next == null && someQueued) {
             next = mOrderedBroadcasts.remove(0);
             if (DEBUG_BROADCAST_DEFERRAL) {
                 Slog.i(TAG, "Next broadcast from main queue: " + next);
diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java
index 91b5234..0e9ee40 100644
--- a/services/core/java/com/android/server/location/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/GnssConfiguration.java
@@ -52,7 +52,6 @@
 
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    //TODO(b/33112647): Create gps_debug.conf with commented career parameters.
     private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf";
 
     // config.xml properties
@@ -191,8 +190,6 @@
             return Collections.EMPTY_LIST;
         }
 
-        // TODO(b/122856486): Validate proxy app names so that a system app or some popular app
-        //                    with location permission is not specified as a proxy app.
         ArrayList proxyApps = new ArrayList(proxyAppsArray.length);
         for (String proxyApp : proxyAppsArray) {
             proxyApps.add(proxyApp);
diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
index 90d16cb..c06b03b 100644
--- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
@@ -373,8 +373,8 @@
         networkAttributes = new NetworkAttributes();
         networkAttributes.mCapabilities = capabilities;
 
-        // TODO(b/119278134): The synchronous method ConnectivityManager.getNetworkInfo() must
-        // not be called inside the asynchronous ConnectivityManager.NetworkCallback methods.
+        // TODO: The synchronous method ConnectivityManager.getNetworkInfo() should not be called
+        //       inside the asynchronous ConnectivityManager.NetworkCallback methods.
         NetworkInfo info = mConnMgr.getNetworkInfo(network);
         if (info != null) {
             networkAttributes.mApn = info.getExtraInfo();
@@ -387,8 +387,8 @@
     }
 
     private void handleSuplConnectionAvailable(Network network) {
-        // TODO(b/119278134): The synchronous method ConnectivityManager.getNetworkInfo() must
-        // not be called inside the asynchronous ConnectivityManager.NetworkCallback methods.
+        // TODO: The synchronous method ConnectivityManager.getNetworkInfo() should not be called
+        //       inside the asynchronous ConnectivityManager.NetworkCallback methods.
         NetworkInfo info = mConnMgr.getNetworkInfo(network);
         String apn = null;
         if (info != null) {
@@ -509,8 +509,8 @@
         }
     }
 
-    // TODO(25876485): Delete this method when all devices upgrade to HAL @2.0::IAGnssCallback
-    //                 interface which does not require setting route to host.
+    // TODO: Delete this method when all devices upgrade to HAL @2.0::IAGnssCallback
+    //       interface which does not require setting route to host.
     private void setRouting() {
         boolean result = mConnMgr.requestRouteToHostAddress(
                 ConnectivityManager.TYPE_MOBILE_SUPL,
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index 20f872a..24ee389 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -18,7 +18,6 @@
 
 import android.annotation.SuppressLint;
 import android.app.AppOpsManager;
-import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -32,11 +31,11 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.StatsLog;
 
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -76,9 +75,9 @@
     private boolean mIsDeviceLocationSettingsEnabled;
 
     // Number of non-framework location access proxy apps is expected to be small (< 5).
-    private static final int HASH_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
-    private HashMap<String, Boolean> mProxyAppToLocationPermissions = new HashMap<>(
-            HASH_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS);
+    private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
+    private ArrayMap<String, Boolean> mProxyAppToLocationPermissions = new ArrayMap<>(
+            ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS);
 
     private PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
             uid -> runOnHandler(() -> handlePermissionsChanged(uid));
@@ -97,10 +96,6 @@
     }
 
     void updateProxyApps(List<String> nfwLocationAccessProxyApps) {
-        // NOTE: This class doesn't explicitly register and listen for SIM_STATE_CHANGED event
-        //       but rather piggy backs on the GnssLocationProvider SIM_STATE_CHANGED handling
-        //       so that the order of processing is preserved. GnssLocationProvider should
-        //       first load the new config parameters for the new SIM and then call this method.
         runOnHandler(() -> handleUpdateProxyApps(nfwLocationAccessProxyApps));
     }
 
@@ -246,15 +241,7 @@
 
     // Represents NfwNotification structure in IGnssVisibilityControlCallback.hal
     private static class NfwNotification {
-        private static final String KEY_PROTOCOL_STACK = "ProtocolStack";
-        private static final String KEY_OTHER_PROTOCOL_STACK_NAME = "OtherProtocolStackName";
-        private static final String KEY_REQUESTOR = "Requestor";
-        private static final String KEY_REQUESTOR_ID = "RequestorId";
-        private static final String KEY_RESPONSE_TYPE = "ResponseType";
-        private static final String KEY_IN_EMERGENCY_MODE = "InEmergencyMode";
-        private static final String KEY_IS_CACHED_LOCATION = "IsCachedLocation";
-
-        // This must match with NfwResponseType enum in IGnssVisibilityControlCallback.hal.
+        // These must match with NfwResponseType enum in IGnssVisibilityControlCallback.hal.
         private static final byte NFW_RESPONSE_TYPE_REJECTED = 0;
         private static final byte NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED = 1;
         private static final byte NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED = 2;
@@ -281,30 +268,14 @@
             mIsCachedLocation = isCachedLocation;
         }
 
-        private void copyFieldsToIntent(Intent intent) {
-            intent.putExtra(KEY_PROTOCOL_STACK, mProtocolStack);
-            if (!TextUtils.isEmpty(mOtherProtocolStackName)) {
-                intent.putExtra(KEY_OTHER_PROTOCOL_STACK_NAME, mOtherProtocolStackName);
-            }
-            intent.putExtra(KEY_REQUESTOR, mRequestor);
-            if (!TextUtils.isEmpty(mRequestorId)) {
-                intent.putExtra(KEY_REQUESTOR_ID, mRequestorId);
-            }
-            intent.putExtra(KEY_RESPONSE_TYPE, mResponseType);
-            intent.putExtra(KEY_IN_EMERGENCY_MODE, mInEmergencyMode);
-            if (mResponseType == NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED) {
-                intent.putExtra(KEY_IS_CACHED_LOCATION, mIsCachedLocation);
-            }
-        }
-
         @SuppressLint("DefaultLocale")
         public String toString() {
             return String.format(
-                    "[Notification] proxyAppPackageName: %s, protocolStack: %d"
-                            + ", otherProtocolStackName: %s, requestor: %d, requestorId: %s"
-                            + ", responseType: %d, inEmergencyMode: %b, isCachedLocation: %b",
-                    mProxyAppPackageName, mProtocolStack, mOtherProtocolStackName,
-                    mRequestor, mRequestorId, mResponseType, mInEmergencyMode, mIsCachedLocation);
+                    "{proxyAppPackageName: %s, protocolStack: %d, otherProtocolStackName: %s, "
+                            + "requestor: %d, requestorId: %s, responseType: %s, inEmergencyMode:"
+                            + " %b, isCachedLocation: %b}",
+                    mProxyAppPackageName, mProtocolStack, mOtherProtocolStackName, mRequestor,
+                    mRequestorId, getResponseTypeAsString(), mInEmergencyMode, mIsCachedLocation);
         }
 
         private String getResponseTypeAsString() {
@@ -405,7 +376,7 @@
     }
 
     private void handleNfwNotification(NfwNotification nfwNotification) {
-        if (DEBUG) Log.d(TAG, nfwNotification.toString());
+        if (DEBUG) Log.d(TAG, "Non-framework location access notification: " + nfwNotification);
 
         final String proxyAppPackageName = nfwNotification.mProxyAppPackageName;
         Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get(
@@ -421,39 +392,27 @@
         logEvent(nfwNotification, isPermissionMismatched);
 
         if (TextUtils.isEmpty(proxyAppPackageName)) {
-            Log.e(TAG, "ProxyAppPackageName field is not set. Not sending intent to proxy app for "
-                    + nfwNotification);
+            Log.e(TAG, "ProxyAppPackageName field is not set. AppOps service not notified "
+                    + "for non-framework location access notification: " + nfwNotification);
             return;
         }
 
         if (isLocationPermissionEnabled == null) {
-            // App is not in the configured list.
-            Log.e(TAG, "Could not find proxy app with name: " + proxyAppPackageName + " in the "
+            Log.w(TAG, "Could not find proxy app with name: " + proxyAppPackageName + " in the "
                     + "value specified for config parameter: "
-                    + GnssConfiguration.CONFIG_NFW_PROXY_APPS + ". Not sending intent to proxy app"
-                    + " for " + nfwNotification);
-            return;
-        }
-
-        // Send intent to non-framework location proxy app with notification information.
-        final Intent intent = new Intent(
-                proxyAppPackageName + NFW_INTENT_ACTION_NFW_LOCATION_ACCESS_SUFFIX);
-        final String proxAppActivityName =
-                proxyAppPackageName + NFW_PROXY_APP_PKG_ACTIVITY_NAME_SUFFIX;
-        intent.setClassName(proxyAppPackageName, proxAppActivityName);
-        intent.setType(NFW_INTENT_TYPE);
-        nfwNotification.copyFieldsToIntent(intent);
-
-        // Check if the proxy app is still installed.
-        final Integer clsAppUid = getApplicationUid(proxyAppPackageName);
-        if (clsAppUid == null || intent.resolveActivity(mPackageManager) == null) {
-            Log.i(TAG, "Proxy application " + proxyAppPackageName + " and/or activity "
-                    + proxAppActivityName + " is not found. Not sending"
-                    + " intent to proxy app for " + nfwNotification);
+                    + GnssConfiguration.CONFIG_NFW_PROXY_APPS + ". AppOps service not notified "
+                    + "for non-framework location access notification: " + nfwNotification);
             return;
         }
 
         // Display location icon attributed to this proxy app.
+        final Integer clsAppUid = getApplicationUid(proxyAppPackageName);
+        if (clsAppUid == null) {
+            Log.e(TAG, "Proxy app " + proxyAppPackageName + " is not found. AppOps service not "
+                    + "notified for non-framework location access notification: "
+                    + nfwNotification);
+            return;
+        }
         mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, clsAppUid, proxyAppPackageName);
 
         // Log proxy app permission mismatch between framework and GNSS HAL.
@@ -461,18 +420,8 @@
             Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPackageName
                     + " location permission is set to " + isLocationPermissionEnabled
                     + " but GNSS non-framework location access response type is "
-                    + nfwNotification.getResponseTypeAsString() + " for " + nfwNotification);
-        }
-
-        // Notify proxy app.
-        try {
-            if (DEBUG) {
-                Log.d(TAG, "Sending non-framework location access notification intent: " + intent);
-            }
-            mContext.startActivityAsUser(intent, UserHandle.getUserHandleForUid(clsAppUid));
-        } catch (ActivityNotFoundException e) {
-            Log.w(TAG, "Activity not found. Failed to send non-framework location access"
-                    + " notification intent to proxy app activity: " + proxAppActivityName);
+                    + nfwNotification.getResponseTypeAsString() + " for notification: "
+                    + nfwNotification);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 7e4365d..ae4ff03 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -120,6 +120,7 @@
             UserManager.DISALLOW_UNMUTE_DEVICE,
             UserManager.DISALLOW_AUTOFILL,
             UserManager.DISALLOW_CONTENT_CAPTURE,
+            UserManager.DISALLOW_CONTENT_SUGGESTIONS,
             UserManager.DISALLOW_USER_SWITCH,
             UserManager.DISALLOW_UNIFIED_PASSWORD,
             UserManager.DISALLOW_CONFIG_LOCATION,
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 7d03d82..16d11ef 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -89,9 +89,6 @@
     @GuardedBy("mLock")
     private ArrayMap<String, Temperature> mTemperatureMap = new ArrayMap<>();
 
-    /** Local PMS handle. */
-    private final PowerManager mPowerManager;
-
     /** HAL wrapper. */
     private ThermalHalWrapper mHalWrapper;
 
@@ -109,7 +106,6 @@
     @VisibleForTesting
     ThermalManagerService(Context context, @Nullable ThermalHalWrapper halWrapper) {
         super(context);
-        mPowerManager = context.getSystemService(PowerManager.class);
         mHalWrapper = halWrapper;
         // Initialize to invalid to send status onActivityManagerReady
         mStatus = INVALID_THROTTLING;
@@ -254,10 +250,11 @@
         }
     }
 
-    private void shutdownIfNeededLocked(Temperature temperature) {
+    private void shutdownIfNeeded(Temperature temperature) {
         if (temperature.getStatus() != Temperature.THROTTLING_SHUTDOWN) {
             return;
         }
+        final PowerManager powerManager = getContext().getSystemService(PowerManager.class);
         switch (temperature.getType()) {
             case Temperature.TYPE_CPU:
                 // Fall through
@@ -266,17 +263,17 @@
             case Temperature.TYPE_NPU:
                 // Fall through
             case Temperature.TYPE_SKIN:
-                mPowerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false);
+                powerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false);
                 break;
             case Temperature.TYPE_BATTERY:
-                mPowerManager.shutdown(false, PowerManager.SHUTDOWN_BATTERY_THERMAL_STATE, false);
+                powerManager.shutdown(false, PowerManager.SHUTDOWN_BATTERY_THERMAL_STATE, false);
                 break;
         }
     }
 
     private void onTemperatureChanged(Temperature temperature, boolean sendStatus) {
+        shutdownIfNeeded(temperature);
         synchronized (mLock) {
-            shutdownIfNeededLocked(temperature);
             Temperature old = mTemperatureMap.put(temperature.getName(), temperature);
             if (old != null) {
                 if (old.getStatus() != temperature.getStatus()) {
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index eed01ae..a8f4a77 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -42,7 +42,6 @@
 import com.android.internal.annotations.GuardedBy;
 
 import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 
 /**
@@ -53,6 +52,7 @@
     private static final String TAG = NetworkStackClient.class.getSimpleName();
 
     private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
+    private static final String IN_PROCESS_SUFFIX = ".InProcess";
 
     private static NetworkStackClient sInstance;
 
@@ -175,42 +175,50 @@
     public void start(Context context) {
         log("Starting network stack");
         mNetworkStackStartRequested = true;
-        // Try to bind in-process if the library is available
-        IBinder connector = null;
-        try {
-            final Class service = Class.forName(
-                    "com.android.server.NetworkStackService",
-                    true /* initialize */,
-                    context.getClassLoader());
-            connector = (IBinder) service.getMethod("makeConnector", Context.class)
-                    .invoke(null, context);
-        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
-            logWtf("Could not create network stack connector from NetworkStackService", e);
-            // TODO: crash/reboot system here ?
-            return;
-        } catch (ClassNotFoundException e) {
-            // Normal behavior if stack is provided by the app: fall through
+
+        final PackageManager pm = context.getPackageManager();
+
+        // Try to bind in-process if the device was shipped with an in-process version
+        Intent intent = getNetworkStackIntent(pm, true /* inSystemProcess */);
+
+        // Otherwise use the updatable module version
+        if (intent == null) {
+            intent = getNetworkStackIntent(pm, false /* inSystemProcess */);
+            log("Starting network stack process");
+        } else {
+            log("Starting network stack in-process");
         }
 
-        // In-process network stack. Add the service to the service manager here.
-        if (connector != null) {
-            log("Registering in-process network stack connector");
-            registerNetworkStackService(connector);
-            return;
-        }
-        // Start the network stack process. The service will be added to the service manager in
-        // NetworkStackConnection.onServiceConnected().
-        log("Starting network stack process");
-        final Intent intent = new Intent(INetworkStackConnector.class.getName());
-        final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
-        intent.setComponent(comp);
-
-        if (comp == null) {
-            logWtf("Could not resolve the network stack with " + intent, null);
+        if (intent == null) {
+            logWtf("Could not resolve the network stack", null);
             // TODO: crash/reboot system server ?
             return;
         }
-        final PackageManager pm = context.getPackageManager();
+
+        // Start the network stack. The service will be added to the service manager in
+        // NetworkStackConnection.onServiceConnected().
+        if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
+                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
+            logWtf("Could not bind to network stack with " + intent, null);
+            return;
+            // TODO: crash/reboot system server if no network stack after a timeout ?
+        }
+
+        log("Network stack service start requested");
+    }
+
+    @Nullable
+    private Intent getNetworkStackIntent(@NonNull PackageManager pm, boolean inSystemProcess) {
+        final String baseAction = INetworkStackConnector.class.getName();
+        final Intent intent =
+                new Intent(inSystemProcess ? baseAction + IN_PROCESS_SUFFIX : baseAction);
+        final ComponentName comp = intent.resolveSystemService(pm, 0);
+
+        if (comp == null) {
+            return null;
+        }
+        intent.setComponent(comp);
+
         int uid = -1;
         try {
             uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
@@ -218,25 +226,27 @@
             logWtf("Network stack package not found", e);
             // Fall through
         }
-        if (uid != Process.NETWORK_STACK_UID) {
+
+        final int expectedUid = inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
+        if (uid != expectedUid) {
             throw new SecurityException("Invalid network stack UID: " + uid);
         }
 
+        if (!inSystemProcess) {
+            checkNetworkStackPermission(pm, comp);
+        }
+
+        return intent;
+    }
+
+    private void checkNetworkStackPermission(
+            @NonNull PackageManager pm, @NonNull ComponentName comp) {
         final int hasPermission =
                 pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
         if (hasPermission != PERMISSION_GRANTED) {
             throw new SecurityException(
                     "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
         }
-
-        if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
-                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
-            logWtf("Could not bind to network stack in-process, or in app with " + intent, null);
-            return;
-            // TODO: crash/reboot system server if no network stack after a timeout ?
-        }
-
-        log("Network stack service start requested");
     }
 
     private void log(@NonNull String message) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 3ebc6ad..e9edba5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -185,6 +185,18 @@
     }
 
     @MediumTest
+    public void testRemoveUserByHandle_ThrowsException() {
+        synchronized (mUserRemoveLock) {
+            try {
+                mUserManager.removeUser(null);
+                fail("Expected IllegalArgumentException on passing in a null UserHandle.");
+            } catch (IllegalArgumentException expected) {
+                // Do nothing - exception is expected.
+            }
+        }
+    }
+
+    @MediumTest
     public void testAddGuest() throws Exception {
         UserInfo userInfo1 = createUser("Guest 1", UserInfo.FLAG_GUEST);
         UserInfo userInfo2 = createUser("Guest 2", UserInfo.FLAG_GUEST);
@@ -520,6 +532,12 @@
         }
     }
 
+    public void testGetUserSwitchability() {
+        int userSwitchable = mUserManager.getUserSwitchability();
+        assertEquals("Expected users to be switchable", UserManager.SWITCHABILITY_STATUS_OK,
+                userSwitchable);
+    }
+
     @LargeTest
     public void testSwitchUser() {
         ActivityManager am = getContext().getSystemService(ActivityManager.class);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index ee60408..0b55794 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -539,9 +539,10 @@
         mFqdn = fqdn;
     }
 
-    /** {@hide} */
-    @SystemApi
-    public @Nullable String getFqdn() {
+    /**
+     * Returns the Fully Qualified Domain Name of the network if it is a Passpoint network.
+     */
+    public @Nullable String getPasspointFqdn() {
         return mFqdn;
     }
 
@@ -550,9 +551,10 @@
         mProviderFriendlyName = providerFriendlyName;
     }
 
-    /** {@hide} */
-    @SystemApi
-    public @Nullable String getProviderFriendlyName() {
+    /**
+     * Returns the Provider Friendly Name of the network if it is a Passpoint network.
+     */
+    public @Nullable String getPasspointProviderFriendlyName() {
         return mProviderFriendlyName;
     }
 
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index b303496..0ce5d66 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -70,7 +70,7 @@
         assertTrue(readWifiInfo.isOsuAp());
         assertTrue(readWifiInfo.isPasspointAp());
         assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getNetworkSuggestionOrSpecifierPackageName());
-        assertEquals(TEST_FQDN, readWifiInfo.getFqdn());
-        assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getProviderFriendlyName());
+        assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
+        assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
     }
 }