Merge changes from topic "userSensitive"

* changes:
  Small issues with FLAG_PERMISSION_USER_SENSITIVE_*
  Introduce and populate PackageManager.FLAG_PERMISSION_USER_VISIBLE
diff --git a/Android.bp b/Android.bp
index fb6ff0f..5e03982 100644
--- a/Android.bp
+++ b/Android.bp
@@ -225,6 +225,7 @@
         "core/java/android/net/INetworkScoreService.aidl",
         "core/java/android/net/INetworkStatsService.aidl",
         "core/java/android/net/INetworkStatsSession.aidl",
+        "core/java/android/net/ITetheringEventCallback.aidl",
         "core/java/android/net/ITetheringStatsProvider.aidl",
         "core/java/android/net/nsd/INsdManager.aidl",
         "core/java/android/nfc/IAppCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index e0aa52f..259bfb1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1204,6 +1204,7 @@
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
+    field public static final int secureElementName = 16844200; // 0x10105a8
     field public static final int seekBarStyle = 16842875; // 0x101007b
     field public static final int segmentedButtonStyle = 16843568; // 0x1010330
     field public static final int selectAllOnFocus = 16843102; // 0x101015e
@@ -3946,7 +3947,7 @@
     method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
     method @Deprecated public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
     method @Deprecated public java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
-    method public boolean isActivityStartAllowedOnDisplay(android.content.Context, int, android.content.Intent);
+    method public boolean isActivityStartAllowedOnDisplay(@NonNull android.content.Context, int, @NonNull android.content.Intent);
     method public boolean isBackgroundRestricted();
     method @Deprecated public boolean isInLockTaskMode();
     method public boolean isLowRamDevice();
@@ -4453,7 +4454,7 @@
     ctor public AutomaticZenRule(android.os.Parcel);
     method public int describeContents();
     method public android.net.Uri getConditionId();
-    method public android.content.ComponentName getConfigurationActivity();
+    method @Nullable public android.content.ComponentName getConfigurationActivity();
     method public long getCreationTime();
     method public int getInterruptionFilter();
     method public String getName();
@@ -4461,7 +4462,7 @@
     method public android.service.notification.ZenPolicy getZenPolicy();
     method public boolean isEnabled();
     method public void setConditionId(android.net.Uri);
-    method public void setConfigurationActivity(android.content.ComponentName);
+    method public void setConfigurationActivity(@Nullable android.content.ComponentName);
     method public void setEnabled(boolean);
     method public void setInterruptionFilter(int);
     method public void setName(String);
@@ -5818,10 +5819,9 @@
     method public void notify(String, int, android.app.Notification);
     method public void notifyAsPackage(@NonNull String, @NonNull String, int, @NonNull android.app.Notification);
     method public boolean removeAutomaticZenRule(String);
-    method public void revokeNotificationDelegate();
     method public void setAutomaticZenRuleState(@NonNull String, @NonNull android.service.notification.Condition);
     method public final void setInterruptionFilter(int);
-    method public void setNotificationDelegate(@NonNull String);
+    method public void setNotificationDelegate(@Nullable String);
     method public void setNotificationPolicy(@NonNull android.app.NotificationManager.Policy);
     method public boolean shouldHideSilentStatusBarIcons();
     method public boolean updateAutomaticZenRule(String, android.app.AutomaticZenRule);
@@ -9655,8 +9655,9 @@
 
   public abstract class Context {
     ctor public Context();
-    method public boolean bindIsolatedService(@RequiresPermission @NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String);
+    method public boolean bindIsolatedService(@RequiresPermission @NonNull android.content.Intent, int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection);
     method public abstract boolean bindService(@RequiresPermission android.content.Intent, @NonNull android.content.ServiceConnection, int);
+    method public boolean bindService(@RequiresPermission @NonNull android.content.Intent, int, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection);
     method @CheckResult(suggest="#enforceCallingOrSelfPermission(String,String)") public abstract int checkCallingOrSelfPermission(@NonNull String);
     method @CheckResult(suggest="#enforceCallingOrSelfUriPermission(Uri,int,String)") public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int);
     method @CheckResult(suggest="#enforceCallingPermission(String,String)") public abstract int checkCallingPermission(@NonNull String);
@@ -25723,7 +25724,7 @@
 
   public static class MediaPlayer2.TrackInfo {
     method @Nullable public android.media.MediaFormat getFormat();
-    method @Nullable public String getLanguage();
+    method @NonNull public String getLanguage();
     method public int getTrackType();
     field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
     field public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
@@ -30088,7 +30089,7 @@
 
   public static final class WifiNetworkSpecifier.Builder {
     ctor public WifiNetworkSpecifier.Builder();
-    method @NonNull public android.net.NetworkSpecifier build();
+    method @NonNull public android.net.wifi.WifiNetworkSpecifier build();
     method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setBssid(@NonNull android.net.MacAddress);
     method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setBssidPattern(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
     method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsEnhancedOpen();
@@ -30910,10 +30911,10 @@
     method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
     method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
     method public boolean removeAidsForService(android.content.ComponentName, String);
-    method public boolean setOffHostForService(android.content.ComponentName, String);
+    method public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
     method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
     method public boolean supportsAidPrefixRegistration();
-    method public boolean unsetOffHostForService(android.content.ComponentName);
+    method public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
     method public boolean unsetPreferredService(android.app.Activity);
     field public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
     field public static final String CATEGORY_OTHER = "other";
@@ -41761,7 +41762,7 @@
     method public int getId();
     method public String getKey();
     method public android.app.Notification getNotification();
-    method public String getOpPkg();
+    method @NonNull public String getOpPkg();
     method public String getOverrideGroupKey();
     method public String getPackageName();
     method public long getPostTime();
diff --git a/api/system-current.txt b/api/system-current.txt
index 1ce3863..ac2073f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1561,23 +1561,25 @@
 
   public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
     method public boolean getAllocateAggressive();
-    method public boolean getAllowDowngrade();
+    method @Deprecated public boolean getAllowDowngrade();
     method public boolean getDontKillApp();
     method @Nullable public String[] getGrantedRuntimePermissions();
     method public boolean getInstallAsFullApp(boolean);
     method public boolean getInstallAsInstantApp(boolean);
     method public boolean getInstallAsVirtualPreload();
+    method public boolean getRequestDowngrade();
   }
 
   public static class PackageInstaller.SessionParams implements android.os.Parcelable {
     method @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) public void setAllocateAggressive(boolean);
-    method public void setAllowDowngrade(boolean);
+    method @Deprecated public void setAllowDowngrade(boolean);
     method public void setDontKillApp(boolean);
     method public void setEnableRollback();
     method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
     method public void setInstallAsInstantApp(boolean);
     method public void setInstallAsVirtualPreload();
+    method public void setRequestDowngrade(boolean);
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
   }
 
@@ -4038,11 +4040,13 @@
     method @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) public String getCaptivePortalServerUrl();
     method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
+    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.net.Network, android.os.Bundle);
     method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
     method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
+    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
     field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
     field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
     field public static final int TETHERING_BLUETOOTH = 2; // 0x2
@@ -4063,6 +4067,11 @@
     method public void onEntitlementResult(int);
   }
 
+  public abstract static class ConnectivityManager.OnTetheringEventCallback {
+    ctor public ConnectivityManager.OnTetheringEventCallback();
+    method public void onUpstreamChanged(@Nullable android.net.Network);
+  }
+
   public final class IpPrefix implements android.os.Parcelable {
     ctor public IpPrefix(java.net.InetAddress, int);
     ctor public IpPrefix(String);
@@ -4725,10 +4734,10 @@
 
   public class WifiManager {
     method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void addWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiUsabilityStatsListener);
-    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
-    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(int, android.net.wifi.WifiManager.ActionListener);
-    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void disable(int, android.net.wifi.WifiManager.ActionListener);
-    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void forget(int, android.net.wifi.WifiManager.ActionListener);
+    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
+    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(int, @Nullable android.net.wifi.WifiManager.ActionListener);
+    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void disable(int, @Nullable android.net.wifi.WifiManager.ActionListener);
+    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void forget(int, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration,java.util.Map<java.lang.Integer,java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(@NonNull java.util.List<android.net.wifi.ScanResult>);
     method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
     method @NonNull @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(@NonNull java.util.Set<android.net.wifi.hotspot2.OsuProvider>);
@@ -4740,7 +4749,7 @@
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
     method public boolean isWifiScannerSupported();
     method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void removeWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.WifiUsabilityStatsListener);
-    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void save(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
+    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission("android.permission.WIFI_SET_DEVICE_MOBILITY_STATE") public void setDeviceMobilityState(int);
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
@@ -9074,7 +9083,7 @@
   public static class ProvisioningManager.Callback {
     ctor public ProvisioningManager.Callback();
     method public void onProvisioningIntChanged(int, int);
-    method public void onProvisioningStringChanged(int, String);
+    method public void onProvisioningStringChanged(int, @NonNull String);
   }
 
 }
diff --git a/api/test-current.txt b/api/test-current.txt
index 166a5ac..4d1d440 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -988,11 +988,29 @@
     method public static boolean isEncodingLinearPcm(int);
   }
 
+  public static final class AudioRecord.MetricsConstants {
+    field public static final String ATTRIBUTES = "android.media.audiorecord.attributes";
+    field public static final String CHANNEL_MASK = "android.media.audiorecord.channelMask";
+    field public static final String DURATION_MS = "android.media.audiorecord.durationMs";
+    field public static final String FRAME_COUNT = "android.media.audiorecord.frameCount";
+    field public static final String PORT_ID = "android.media.audiorecord.portId";
+    field public static final String START_COUNT = "android.media.audiorecord.startCount";
+  }
+
   public final class AudioRecordingConfiguration implements android.os.Parcelable {
     ctor public AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]);
     ctor public AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String);
   }
 
+  public static final class AudioTrack.MetricsConstants {
+    field public static final String ATTRIBUTES = "android.media.audiotrack.attributes";
+    field public static final String CHANNEL_MASK = "android.media.audiotrack.channelMask";
+    field public static final String ENCODING = "android.media.audiotrack.encoding";
+    field public static final String FRAME_COUNT = "android.media.audiotrack.frameCount";
+    field public static final String PORT_ID = "android.media.audiotrack.portId";
+    field public static final String SAMPLE_RATE = "android.media.audiotrack.sampleRate";
+  }
+
   public final class BufferingParams implements android.os.Parcelable {
     method public int describeContents();
     method public int getInitialMarkMs();
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 4e540b1..b812c80 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -521,7 +521,7 @@
         ADD_PSS_EXTERNAL_SLOW = 4;
     }
     optional Type type = 7;
-    optional int64 duration = 8;
+    optional int64 duration_millis = 8;
 }
 
 /**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index c067f9d..023371d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2018,7 +2018,8 @@
      * @return {@code true} if a call to start an activity on the target display is allowed for the
      * provided context and no {@link SecurityException} will be thrown, {@code false} otherwise.
      */
-    public boolean isActivityStartAllowedOnDisplay(Context context, int displayId, Intent intent) {
+    public boolean isActivityStartAllowedOnDisplay(@NonNull Context context, int displayId,
+            @NonNull Intent intent) {
         try {
             return getTaskService().isActivityStartAllowedOnDisplay(displayId, intent,
                     intent.resolveTypeIfNeeded(context.getContentResolver()), context.getUserId());
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 010a900..ec2825e 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -136,7 +136,7 @@
      * Returns the {@link ComponentName} of the activity that shows configuration options
      * for this rule.
      */
-    public ComponentName getConfigurationActivity() {
+    public @Nullable ComponentName getConfigurationActivity() {
         return configurationActivity;
     }
 
@@ -237,9 +237,10 @@
     /**
      * Sets the configuration activity - an activity that handles
      * {@link NotificationManager#ACTION_AUTOMATIC_ZEN_RULE} that shows the user more information
-     * about this rule and/or allows them to configure it.
+     * about this rule and/or allows them to configure it. This is required to be non-null for rules
+     * that are not backed by {@link android.service.notification.ConditionProviderService}.
      */
-    public void setConfigurationActivity(ComponentName componentName) {
+    public void setConfigurationActivity(@Nullable ComponentName componentName) {
         this.configurationActivity = componentName;
     }
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index daf2366..5945eef 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -145,10 +145,17 @@
     }
 
     @Override
-    public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
-            String instanceName) {
+    public boolean bindService(
+          Intent service, int flags, Executor executor, ServiceConnection conn) {
         throw new ReceiverCallNotAllowedException(
-                "BroadcastReceiver components are not allowed to bind to services");
+            "BroadcastReceiver components are not allowed to bind to services");
+    }
+
+    @Override
+    public boolean bindIsolatedService(Intent service, int flags, String instanceName,
+            Executor executor, ServiceConnection conn) {
+        throw new ReceiverCallNotAllowedException(
+            "BroadcastReceiver components are not allowed to bind to services");
     }
 }
 
@@ -1639,28 +1646,34 @@
     }
 
     @Override
-    public boolean bindService(Intent service, ServiceConnection conn,
-            int flags) {
+    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
         warnIfCallingFromSystemProcess();
-        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), getUser());
+        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
+                getUser());
     }
 
     @Override
-    public boolean bindIsolatedService(Intent service, ServiceConnection conn,
-            int flags, String instanceName) {
+    public boolean bindService(
+            Intent service, int flags, Executor executor, ServiceConnection conn) {
+        warnIfCallingFromSystemProcess();
+        return bindServiceCommon(service, conn, flags, null, null, executor, getUser());
+    }
+
+    @Override
+    public boolean bindIsolatedService(Intent service, int flags, String instanceName,
+            Executor executor, ServiceConnection conn) {
         warnIfCallingFromSystemProcess();
         if (instanceName == null) {
             throw new NullPointerException("null instanceName");
         }
-        return bindServiceCommon(service, conn, flags, instanceName, mMainThread.getHandler(),
-                getUser());
+        return bindServiceCommon(service, conn, flags, instanceName, null, executor, getUser());
     }
 
     /** @hide */
     @Override
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
             UserHandle user) {
-        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), user);
+        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, user);
     }
 
     /** @hide */
@@ -1670,7 +1683,7 @@
         if (handler == null) {
             throw new IllegalArgumentException("handler must not be null.");
         }
-        return bindServiceCommon(service, conn, flags, null, handler, user);
+        return bindServiceCommon(service, conn, flags, null, handler, null, user);
     }
 
     /** @hide */
@@ -1693,15 +1706,21 @@
     }
 
     private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
-            String instanceName, Handler
-            handler, UserHandle user) {
+            String instanceName, Handler handler, Executor executor, UserHandle user) {
         // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
         IServiceConnection sd;
         if (conn == null) {
             throw new IllegalArgumentException("connection is null");
         }
+        if (handler != null && executor != null) {
+            throw new IllegalArgumentException("Handler and Executor both supplied");
+        }
         if (mPackageInfo != null) {
-            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
+            if (executor != null) {
+                sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
+            } else {
+                sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
+            }
         } else {
             throw new RuntimeException("Not supported in system context");
         }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index e1da08b..29e6807 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -192,7 +192,6 @@
     ParceledListSlice getAppActiveNotifications(String callingPkg, int userId);
 
     void setNotificationDelegate(String callingPkg, String delegate);
-    void revokeNotificationDelegate(String callingPkg);
     String getNotificationDelegate(String callingPkg);
     boolean canNotifyAsPackage(String callingPkg, String targetPkg);
 
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 5d186a2..db8c905 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -76,6 +76,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 final class IntentReceiverLeaked extends AndroidRuntimeException {
     @UnsupportedAppUsage
@@ -1651,6 +1652,16 @@
     @UnsupportedAppUsage
     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
             Context context, Handler handler, int flags) {
+        return getServiceDispatcherCommon(c, context, handler, null, flags);
+    }
+
+    public final IServiceConnection getServiceDispatcher(ServiceConnection c,
+            Context context, Executor executor, int flags) {
+        return getServiceDispatcherCommon(c, context, null, executor, flags);
+    }
+
+    private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
+            Context context, Handler handler, Executor executor, int flags) {
         synchronized (mServices) {
             LoadedApk.ServiceDispatcher sd = null;
             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
@@ -1659,7 +1670,11 @@
                 sd = map.get(c);
             }
             if (sd == null) {
-                sd = new ServiceDispatcher(c, context, handler, flags);
+                if (executor != null) {
+                    sd = new ServiceDispatcher(c, context, executor, flags);
+                } else {
+                    sd = new ServiceDispatcher(c, context, handler, flags);
+                }
                 if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
                 if (map == null) {
                     map = new ArrayMap<>();
@@ -1667,7 +1682,7 @@
                 }
                 map.put(c, sd);
             } else {
-                sd.validate(context, handler);
+                sd.validate(context, handler, executor);
             }
             return sd.getIServiceConnection();
         }
@@ -1744,6 +1759,7 @@
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         private final Context mContext;
         private final Handler mActivityThread;
+        private final Executor mActivityExecutor;
         private final ServiceConnectionLeaked mLocation;
         private final int mFlags;
 
@@ -1783,12 +1799,25 @@
             mConnection = conn;
             mContext = context;
             mActivityThread = activityThread;
+            mActivityExecutor = null;
             mLocation = new ServiceConnectionLeaked(null);
             mLocation.fillInStackTrace();
             mFlags = flags;
         }
 
-        void validate(Context context, Handler activityThread) {
+        ServiceDispatcher(ServiceConnection conn,
+                Context context, Executor activityExecutor, int flags) {
+            mIServiceConnection = new InnerConnection(this);
+            mConnection = conn;
+            mContext = context;
+            mActivityThread = null;
+            mActivityExecutor = activityExecutor;
+            mLocation = new ServiceConnectionLeaked(null);
+            mLocation.fillInStackTrace();
+            mFlags = flags;
+        }
+
+        void validate(Context context, Handler activityThread, Executor activityExecutor) {
             if (mContext != context) {
                 throw new RuntimeException(
                     "ServiceConnection " + mConnection +
@@ -1801,6 +1830,12 @@
                     " registered with differing handler (was " +
                     mActivityThread + " now " + activityThread + ")");
             }
+            if (mActivityExecutor != activityExecutor) {
+                throw new RuntimeException(
+                    "ServiceConnection " + mConnection +
+                    " registered with differing executor (was " +
+                    mActivityExecutor + " now " + activityExecutor + ")");
+            }
         }
 
         void doForget() {
@@ -1840,7 +1875,9 @@
         }
 
         public void connected(ComponentName name, IBinder service, boolean dead) {
-            if (mActivityThread != null) {
+            if (mActivityExecutor != null) {
+                mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
+            } else if (mActivityThread != null) {
                 mActivityThread.post(new RunConnection(name, service, 0, dead));
             } else {
                 doConnected(name, service, dead);
@@ -1848,7 +1885,9 @@
         }
 
         public void death(ComponentName name, IBinder service) {
-            if (mActivityThread != null) {
+            if (mActivityExecutor != null) {
+                mActivityExecutor.execute(new RunConnection(name, service, 1, false));
+            } else if (mActivityThread != null) {
                 mActivityThread.post(new RunConnection(name, service, 1, false));
             } else {
                 doDeath(name, service);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index edf86f9..ed7aa4a 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -589,11 +589,11 @@
      * received on your behalf from the cloud, without your process having to wake up.
      *
      * You can check if you have an allowed delegate with {@link #getNotificationDelegate()} and
-     * revoke your delegate with {@link #revokeNotificationDelegate()}.
+     * revoke your delegate by passing null to this method.
      *
      * @param delegate Package name of the app which can send notifications on your behalf.
      */
-    public void setNotificationDelegate(@NonNull String delegate) {
+    public void setNotificationDelegate(@Nullable String delegate) {
         INotificationManager service = getService();
         String pkg = mContext.getPackageName();
         if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
@@ -605,20 +605,6 @@
     }
 
     /**
-     * Revokes permission for your {@link #setNotificationDelegate(String) notification delegate}
-     * to post notifications on your behalf.
-     */
-    public void revokeNotificationDelegate() {
-        INotificationManager service = getService();
-        String pkg = mContext.getPackageName();
-        try {
-            service.revokeNotificationDelegate(pkg);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Returns the {@link #setNotificationDelegate(String) delegate} that can post notifications on
      * your behalf, if there currently is one.
      */
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 41995288..f28718c 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.annotation.AttrRes;
+import android.annotation.CallbackExecutor;
 import android.annotation.CheckResult;
 import android.annotation.ColorInt;
 import android.annotation.ColorRes;
@@ -2967,26 +2968,40 @@
             @NonNull ServiceConnection conn, @BindServiceFlags int flags);
 
     /**
+     * Same as {@link #bindService(Intent, ServiceConnection, int)} with executor to control
+     * ServiceConnection callbacks.
+     * @param executor Callbacks on ServiceConnection will be called on executor. Must use same
+     *      instance for the same instance of ServiceConnection.
+     */
+    public boolean bindService(@RequiresPermission @NonNull Intent service,
+            @BindServiceFlags int flags, @NonNull @CallbackExecutor Executor executor,
+            @NonNull ServiceConnection conn) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * Variation of {@link #bindService} that, in the specific case of isolated
      * services, allows the caller to generate multiple instances of a service
      * from a single component declaration.
      *
      * @param service Identifies the service to connect to.  The Intent must
      *      specify an explicit component name.
-     * @param conn Receives information as the service is started and stopped.
-     *      This must be a valid ServiceConnection object; it must not be null.
      * @param flags Operation options for the binding as per {@link #bindService}.
      * @param instanceName Unique identifier for the service instance.  Each unique
      *      name here will result in a different service instance being created.
      * @return Returns success of binding as per {@link #bindService}.
+     * @param executor Callbacks on ServiceConnection will be called on executor.
+     *      Must use same instance for the same instance of ServiceConnection.
+     * @param conn Receives information as the service is started and stopped.
+     *      This must be a valid ServiceConnection object; it must not be null.
      *
      * @throws SecurityException If the caller does not have permission to access the service
      *
      * @see #bindService
      */
     public boolean bindIsolatedService(@RequiresPermission @NonNull Intent service,
-            @NonNull ServiceConnection conn, @BindServiceFlags int flags,
-            @NonNull String instanceName) {
+            @BindServiceFlags int flags, @NonNull String instanceName,
+            @NonNull @CallbackExecutor Executor executor, @NonNull ServiceConnection conn) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
 
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 40559d3..0859f97 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -706,9 +706,15 @@
     }
 
     @Override
-    public boolean bindIsolatedService(Intent service, ServiceConnection conn,
-            int flags, String instanceName) {
-        return mBase.bindIsolatedService(service, conn, flags, instanceName);
+    public boolean bindService(Intent service, int flags, Executor executor,
+            ServiceConnection conn) {
+        return mBase.bindService(service, flags, executor, conn);
+    }
+
+    @Override
+    public boolean bindIsolatedService(Intent service, int flags, String instanceName,
+            Executor executor, ServiceConnection conn) {
+        return mBase.bindIsolatedService(service, flags, instanceName, executor, conn);
     }
 
     /** @hide */
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 7de8105..d758c4d 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1342,8 +1342,8 @@
          * @hide
          */
         public boolean areHiddenOptionsSet() {
-            return (installFlags & (PackageManager.INSTALL_ALLOW_DOWNGRADE
-                    | PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE
+            return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE
+                    | PackageManager.INSTALL_ALLOW_DOWNGRADE
                     | PackageManager.INSTALL_DONT_KILL_APP
                     | PackageManager.INSTALL_INSTANT_APP
                     | PackageManager.INSTALL_FULL_APP
@@ -1455,13 +1455,23 @@
             installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
         }
 
+        /**
+         * @deprecated use {@link #setRequestDowngrade(boolean)}.
+         * {@hide}
+         */
+        @SystemApi
+        @Deprecated
+        public void setAllowDowngrade(boolean allowDowngrade) {
+            setRequestDowngrade(allowDowngrade);
+        }
+
         /** {@hide} */
         @SystemApi
-        public void setAllowDowngrade(boolean allowDowngrade) {
-            if (allowDowngrade) {
-                installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
+        public void setRequestDowngrade(boolean requestDowngrade) {
+            if (requestDowngrade) {
+                installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
             } else {
-                installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE;
+                installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
             }
         }
 
@@ -1982,11 +1992,23 @@
         /**
          * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
          *
+         * @deprecated use {@link #getRequestDowngrade()}.
          * @hide
          */
         @SystemApi
+        @Deprecated
         public boolean getAllowDowngrade() {
-            return (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
+            return getRequestDowngrade();
+        }
+
+        /**
+         * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}.
+         *
+         * @hide
+         */
+        @SystemApi
+        public boolean getRequestDowngrade() {
+            return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0;
         }
 
         /**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 02272e5..7d05d50 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -710,7 +710,7 @@
             INSTALL_INTERNAL,
             INSTALL_FROM_ADB,
             INSTALL_ALL_USERS,
-            INSTALL_ALLOW_DOWNGRADE,
+            INSTALL_REQUEST_DOWNGRADE,
             INSTALL_GRANT_RUNTIME_PERMISSIONS,
             INSTALL_FORCE_VOLUME_UUID,
             INSTALL_FORCE_PERMISSION_PROMPT,
@@ -721,7 +721,7 @@
             INSTALL_VIRTUAL_PRELOAD,
             INSTALL_APEX,
             INSTALL_ENABLE_ROLLBACK,
-            INSTALL_RESPECT_ALLOW_DOWNGRADE,
+            INSTALL_ALLOW_DOWNGRADE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface InstallFlags {}
@@ -768,14 +768,21 @@
     public static final int INSTALL_ALL_USERS = 0x00000040;
 
     /**
-     * Flag parameter for {@link #installPackage} to indicate that it is okay
-     * to install an update to an app where the newly installed app has a lower
-     * version code than the currently installed app. This is permitted only if
-     * the currently installed app is marked debuggable.
+     * Flag parameter for {@link #installPackage} to indicate that an upgrade to a lower version
+     * of a package than currently installed has been requested.
+     *
+     * <p>Note that this flag doesn't guarantee that downgrade will be performed. That decision
+     * depends
+     * on whenever:
+     * <ul>
+     * <li>An app is debuggable.
+     * <li>Or a build is debuggable.
+     * <li>Or {@link #INSTALL_ALLOW_DOWNGRADE} is set.
+     * </ul>
      *
      * @hide
      */
-    public static final int INSTALL_ALLOW_DOWNGRADE = 0x00000080;
+    public static final int INSTALL_REQUEST_DOWNGRADE = 0x00000080;
 
     /**
      * Flag parameter for {@link #installPackage} to indicate that all runtime
@@ -868,12 +875,11 @@
 
     /**
      * Flag parameter for {@link #installPackage} to indicate that
-     * {@link #INSTALL_ALLOW_DOWNGRADE} should be respected.
+     * {@link #INSTALL_REQUEST_DOWNGRADE} should be allowed.
      *
      * @hide
      */
-    // TODO(b/127322579): rename
-    public static final int INSTALL_RESPECT_ALLOW_DOWNGRADE = 0x00100000;
+    public static final int INSTALL_ALLOW_DOWNGRADE = 0x00100000;
 
     /** @hide */
     @IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 0497f8c..fb0821e 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -56,6 +56,7 @@
 import android.util.Log;
 import android.util.SparseIntArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.Preconditions;
@@ -2542,6 +2543,94 @@
     }
 
     /**
+     * Callback for use with {@link registerTetheringEventCallback} to find out tethering
+     * upstream status.
+     *
+     *@hide
+     */
+    @SystemApi
+    public abstract static class OnTetheringEventCallback {
+
+        /**
+         * Called when tethering upstream changed. This can be called multiple times and can be
+         * called any time.
+         *
+         * @param network the {@link Network} of tethering upstream. Null means tethering doesn't
+         * have any upstream.
+         */
+        public void onUpstreamChanged(@Nullable Network network) {}
+    }
+
+    @GuardedBy("mTetheringEventCallbacks")
+    private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
+            mTetheringEventCallbacks = new ArrayMap<>();
+
+    /**
+     * Start listening to tethering change events. Any new added callback will receive the last
+     * tethering status right away. If callback is registered when tethering loses its upstream or
+     * disabled, {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called
+     * with a null argument. The same callback object cannot be registered twice.
+     *
+     * @param executor the executor on which callback will be invoked.
+     * @param callback the callback to be called when tethering has change events.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+    public void registerTetheringEventCallback(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull final OnTetheringEventCallback callback) {
+        Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
+
+        synchronized (mTetheringEventCallbacks) {
+            Preconditions.checkArgument(!mTetheringEventCallbacks.containsKey(callback),
+                    "callback was already registered.");
+            ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
+                @Override
+                public void onUpstreamChanged(Network network) throws RemoteException {
+                    Binder.withCleanCallingIdentity(() ->
+                            executor.execute(() -> {
+                                callback.onUpstreamChanged(network);
+                            }));
+                }
+            };
+            try {
+                String pkgName = mContext.getOpPackageName();
+                Log.i(TAG, "registerTetheringUpstreamCallback:" + pkgName);
+                mService.registerTetheringEventCallback(remoteCallback, pkgName);
+                mTetheringEventCallbacks.put(callback, remoteCallback);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Remove tethering event callback previously registered with
+     * {@link #registerTetheringEventCallback}.
+     *
+     * @param callback previously registered callback.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+    public void unregisterTetheringEventCallback(
+            @NonNull final OnTetheringEventCallback callback) {
+        synchronized (mTetheringEventCallbacks) {
+            ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
+            Preconditions.checkNotNull(remoteCallback, "callback was not registered.");
+            try {
+                String pkgName = mContext.getOpPackageName();
+                Log.i(TAG, "unregisterTetheringEventCallback:" + pkgName);
+                mService.unregisterTetheringEventCallback(remoteCallback, pkgName);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+
+    /**
      * Get the list of regular expressions that define any tetherable
      * USB network interfaces.  If USB tethering is not supported by the
      * device, this list should be empty.
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index fd44fc8..a425a91 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.net.ConnectionInfo;
 import android.net.LinkProperties;
+import android.net.ITetheringEventCallback;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
@@ -214,4 +215,7 @@
 
     void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
             boolean showEntitlementUi, String callerPkg);
+
+    void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+    void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
 }
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/core/java/android/net/ITetheringEventCallback.aidl
new file mode 100644
index 0000000..d502088
--- /dev/null
+++ b/core/java/android/net/ITetheringEventCallback.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.Network;
+
+/**
+ * Callback class for receiving tethering changed events
+ * @hide
+ */
+oneway interface ITetheringEventCallback
+{
+    void onUpstreamChanged(in Network network);
+}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 01932ab..f23dc2d 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -16,6 +16,7 @@
 
 package android.nfc.cardemulation;
 
+import android.annotation.NonNull;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Activity;
@@ -359,7 +360,7 @@
      * @param service The component name of the service
      * @return whether the registration was successful.
      */
-    public boolean unsetOffHostForService(ComponentName service) {
+    public boolean unsetOffHostForService(@NonNull ComponentName service) {
         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
         if (adapter == null) {
             return false;
@@ -405,7 +406,8 @@
      * @param offHostSecureElement Secure Element to register the AID to
      * @return whether the registration was successful.
      */
-    public boolean setOffHostForService(ComponentName service, String offHostSecureElement) {
+    public boolean setOffHostForService(@NonNull ComponentName service,
+            @NonNull String offHostSecureElement) {
         boolean validSecureElement = false;
 
         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 650d217..39e9138 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.app.Activity;
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -65,6 +67,9 @@
     private static final String ANGLE_RULES_FILE = "a4a_rules.json";
     private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
     private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID";
+    private static final String ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE =
+            "android.app.action.ANGLE_FOR_ANDROID_TOAST_MESSAGE";
+    private static final String INTENT_KEY_A4A_TOAST_MESSAGE = "A4A Toast Message";
     private static final String GAME_DRIVER_WHITELIST_ALL = "*";
 
     private ClassLoader mClassLoader;
@@ -557,9 +562,20 @@
         final String packageName = context.getPackageName();
 
         if (shouldShowAngleInUseDialogBox(context) && shouldUseAngle(context, packageName)) {
-            final String toastMsg = packageName + " is using ANGLE";
-            final Toast toast = Toast.makeText(context, toastMsg, Toast.LENGTH_LONG);
-            toast.show();
+            final Intent intent = new Intent(ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE);
+            String anglePkg = getAnglePackageName(context.getPackageManager());
+            intent.setPackage(anglePkg);
+
+            context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    Bundle results = getResultExtras(true);
+
+                    String toastMsg = results.getString(INTENT_KEY_A4A_TOAST_MESSAGE);
+                    final Toast toast = Toast.makeText(context, toastMsg, Toast.LENGTH_LONG);
+                    toast.show();
+                }
+            }, null, Activity.RESULT_OK, null, null);
         }
     }
 
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index 8880296..e656466 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -349,16 +349,31 @@
         dialog.show();
     }
 
+    /**
+     * Get the DecorView.
+     * @return the DecorView for the current dialog window, if it exists.
+     * If the window does not exist, null is returned.
+     */
+    private View getDecorView() {
+        if (mDialog != null && mDialog.getWindow() != null) {
+            return mDialog.getWindow().getDecorView();
+        }
+        return null;
+    }
+
     void postDismiss() {
         removeDismissCallbacks();
-        View decorView = mDialog.getWindow().getDecorView();
-        decorView.post(mDismissRunnable);
+        View decorView = getDecorView();
+        if (decorView != null) {
+            // If decorView is null, dialog was already dismissed
+            decorView.post(mDismissRunnable);
+        }
     }
 
     private void removeDismissCallbacks() {
-        if (mDialog != null && mDialog.getWindow() != null
-                && mDialog.getWindow().getDecorView() != null) {
-            mDialog.getWindow().getDecorView().removeCallbacks(mDismissRunnable);
+        View decorView = getDecorView();
+        if (decorView != null) {
+            decorView.removeCallbacks(mDismissRunnable);
         }
     }
 
diff --git a/core/java/android/provider/TEST_MAPPING b/core/java/android/provider/TEST_MAPPING
new file mode 100644
index 0000000..7486f7f
--- /dev/null
+++ b/core/java/android/provider/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.provider.SettingsBackupTest"
+        }
+      ]
+    }
+  ]
+}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 0836327..4315100 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -16,6 +16,7 @@
 
 package android.service.notification;
 
+import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -299,7 +300,7 @@
      * Might be different from {@link #getPackageName()} if the app owning the notification has
      * a {@link NotificationManager#setNotificationDelegate(String) notification delegate}.
      */
-    public String getOpPkg() {
+    public @NonNull String getOpPkg() {
         return opPkg;
     }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a3d0a7e..9222bd6 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2372,6 +2372,9 @@
                     mAttachInfo.mOutsets.set(mPendingOutsets);
                     mApplyInsetsRequested = false;
                     dispatchApplyInsets(host);
+                    // We applied insets so force contentInsetsChanged to ensure the
+                    // hierarchy is measured below.
+                    contentInsetsChanged = true;
                 }
                 if (visibleInsetsChanged) {
                     mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
diff --git a/core/java/android/view/contentcapture/ContentCaptureHelper.java b/core/java/android/view/contentcapture/ContentCaptureHelper.java
index 6e84ff0..6bc3829 100644
--- a/core/java/android/view/contentcapture/ContentCaptureHelper.java
+++ b/core/java/android/view/contentcapture/ContentCaptureHelper.java
@@ -20,7 +20,6 @@
 import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_OFF;
 import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_VERBOSE;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Build;
 import android.provider.DeviceConfig;
@@ -48,21 +47,6 @@
     }
 
     /**
-     * Gets the value of a device config property from the Content Capture namespace.
-     */
-    public static int getIntDeviceConfigProperty(@NonNull String key, int defaultValue) {
-        final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE, key);
-        if (value == null) return defaultValue;
-
-        try {
-            return Integer.parseInt(value);
-        } catch (Exception e) {
-            Log.w(TAG, "error parsing value (" + value + ") of property " + key + ": " + e);
-            return defaultValue;
-        }
-    }
-
-    /**
      * Gets the default logging level for the device.
      */
     @LoggingLevel
@@ -75,8 +59,8 @@
      */
     public static void setLoggingLevel() {
         final int defaultLevel = getDefaultLoggingLevel();
-        final int level = getIntDeviceConfigProperty(DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
-                defaultLevel);
+        final int level = DeviceConfig.getInt(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL, defaultLevel);
         setLoggingLevel(level);
     }
 
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index f4c904d..7270302 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -480,6 +480,11 @@
         return mDestroyed;
     }
 
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + mComponentName + "]";
+    }
+
     /**
      * Base class for the requests serviced by the remote service.
      *
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index aa1e0d4..5688870 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -212,7 +212,7 @@
                 // It helps to keep the memory usage down when sampling is enabled.
                 final CallStat callStat = uidEntry.get(
                         callingUid, s.binderClass, s.transactionCode,
-                        mDeviceState.isScreenInteractive());
+                        screenInteractive);
                 if (callStat != null) {
                     callStat.callCount++;
                 }
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b48c6b0..840cd63 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2941,6 +2941,7 @@
         <!-- @hide @SystemApi -->
         <public name="allowClearUserDataOnFailedRestore"/>
         <public name="allowAudioPlaybackCapture"/>
+        <public name="secureElementName" />
     </public-group>
 
     <public-group type="drawable" first-id="0x010800b4">
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
index a88968b..1cb71f9 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
@@ -20,6 +20,7 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Mockito.doAnswer;
@@ -33,6 +34,8 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.google.common.base.Throwables;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -588,6 +591,29 @@
         }
     }
 
+    @Test
+    public void addSameParentNodeWithDifferentChildNode_whenOriginalChildHasChild_doesntCrash() {
+        AccessibilityNodeInfo parentNodeInfo = getParentNode();
+        AccessibilityNodeInfo childNodeInfo = getChildNode();
+        childNodeInfo.addChild(getMockViewWithA11yAndWindowIds(CHILD_VIEW_ID + 1, WINDOW_ID_1));
+
+        AccessibilityNodeInfo replacementParentNodeInfo =
+                getNodeWithA11yAndWindowId(PARENT_VIEW_ID, WINDOW_ID_1);
+        replacementParentNodeInfo.addChild(
+                getMockViewWithA11yAndWindowIds(OTHER_CHILD_VIEW_ID, WINDOW_ID_1));
+        try {
+            mAccessibilityCache.add(parentNodeInfo);
+            mAccessibilityCache.add(childNodeInfo);
+            mAccessibilityCache.add(replacementParentNodeInfo);
+        } catch (IllegalStateException e) {
+            fail("recycle A11yNodeInfo twice" + Throwables.getStackTraceAsString(e));
+        } finally {
+            parentNodeInfo.recycle();
+            childNodeInfo.recycle();
+            replacementParentNodeInfo.recycle();
+        }
+    }
+
     private void assertNodeIsRefreshedWithEventType(int eventType, int contentChangeTypes) {
         AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
         mAccessibilityCache.add(nodeInfo);
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index e375af3..c4632f7 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -718,6 +718,36 @@
         assertEquals(2, callStats.recordedCallCount);
     }
 
+    @Test
+    public void testTrackScreenInteractiveDisabled_sampling() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setSamplingInterval(2);
+        bcs.setTrackScreenInteractive(false);
+        Binder binder = new Binder();
+
+        mDeviceState.setScreenInteractive(false);
+        CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+
+        mDeviceState.setScreenInteractive(true);
+        callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID);
+        bcs.time += 1000;  // shoud be ignored.
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(1, uidEntries.size());
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID);
+        Assert.assertNotNull(uidEntry);
+        assertEquals(2, uidEntry.callCount);
+
+        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+        assertEquals(1, callStatsList.size());
+        BinderCallsStats.CallStat callStats = callStatsList.get(0);
+        assertEquals(false, callStats.screenInteractive);
+        assertEquals(2, callStats.callCount);
+        assertEquals(1, callStats.recordedCallCount);
+    }
 
     class TestBinderCallsStats extends BinderCallsStats {
         public int callingUid = CALLING_UID;
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index c3bcbb4..5e48ea1 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -135,6 +135,36 @@
  *     }
  * </pre>
  *
+ * <p>A few of the properties may at first appear redundant, such as {@link #setElevation(float)}
+ * and {@link #setTranslationZ(float)}. The reason for these duplicates are to allow for a
+ * separation between static & transient usages. For example consider a button that raises from 2dp
+ * to 8dp when pressed. To achieve that an application may decide to setElevation(2dip), and then
+ * on press to animate setTranslationZ to 6dip. Combined this achieves the final desired 8dip
+ * value, but the animation need only concern itself with animating the lift from press without
+ * needing to know the initial starting value. {@link #setTranslationX(float)} and
+ * {@link #setTranslationY(float)} are similarly provided for animation uses despite the functional
+ * overlap with {@link #setPosition(Rect)}.
+ *
+ * <p>The RenderNode's transform matrix is computed at render time as follows:
+ * First a setTranslate(getTranslationX(), getTranslationY()) is applied to a {@link Matrix}.
+ * Second a preRotate(getRotationZ(), getPivotX(), getPivotY()) is applied to the matrix. And
+ * finally a preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY()) is applied. The current
+ * canvas transform matrix, which is translated to the RenderNode's position,
+ * is then multiplied by the RenderNode's transform matrix. Therefore there is no implicit
+ * ordering in setting various RenderNode properties. That is to say that:
+ *
+ * <pre class="prettyprint">
+ *     renderNode.setTranslationX(100);
+ *     renderNode.setScaleX(100);
+ * </pre>
+ *
+ * is equivalent to
+ *
+ * <pre class="prettyprint">
+ *     renderNode.setScaleX(100);
+ *     renderNode.setTranslationX(100);
+ * </pre>
+ *
  * <h3>Threading</h3>
  * <p>RenderNode may be created and used on any thread but they are not thread-safe. Only
  * a single thread may interact with a RenderNode at any given time. It is critical
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 8e57a3a..091775dbe7 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -401,11 +401,11 @@
     SkRect dirty;
     mDamageAccumulator.finish(&dirty);
 
-    // TODO: Re-enable after figuring out cause of b/22592975
-    //    if (dirty.isEmpty() && Properties::skipEmptyFrames) {
-    //        mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
-    //        return;
-    //    }
+    if (dirty.isEmpty() && Properties::skipEmptyFrames
+            && !surfaceRequiresRedraw()) {
+        mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
+        return;
+    }
 
     mCurrentFrameInfo->markIssueDrawCommandsStart();
 
@@ -638,6 +638,19 @@
     return mFrameNumber;
 }
 
+bool CanvasContext::surfaceRequiresRedraw() {
+    if (!mNativeSurface) return false;
+    if (mHaveNewSurface) return true;
+
+    int width = -1;
+    int height = -1;
+    ReliableSurface* surface = mNativeSurface.get();
+    surface->query(NATIVE_WINDOW_WIDTH, &width);
+    surface->query(NATIVE_WINDOW_HEIGHT, &height);
+
+    return width == mLastFrameWidth && height == mLastFrameHeight;
+}
+
 SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
     if (frame.width() != mLastFrameWidth || frame.height() != mLastFrameHeight) {
         // can't rely on prior content of window if viewport size changes
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index db97763..4da0eac 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -217,6 +217,7 @@
     void freePrefetchedLayers();
 
     bool isSwapChainStuffed();
+    bool surfaceRequiresRedraw();
 
     SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
 
diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java
index f6b2031..5cd3621 100644
--- a/media/apex/java/android/media/MediaPlayer2.java
+++ b/media/apex/java/android/media/MediaPlayer2.java
@@ -1985,7 +1985,7 @@
          * When the language is unknown or could not be determined,
          * ISO-639-2 language code, "und", is returned.
          */
-        public @Nullable String getLanguage() {
+        public @NonNull String getLanguage() {
             String language = mFormat.getString(MediaFormat.KEY_LANGUAGE);
             return language == null ? "und" : language;
         }
diff --git a/media/apex/java/android/media/MediaSession2.java b/media/apex/java/android/media/MediaSession2.java
index 148e16c..09ac9ca 100644
--- a/media/apex/java/android/media/MediaSession2.java
+++ b/media/apex/java/android/media/MediaSession2.java
@@ -749,6 +749,10 @@
          * You can reject the connection by returning {@code null}. In that case, controller
          * receives {@link MediaController2.ControllerCallback#onDisconnected(MediaController2)}
          * and cannot be used.
+         * <p>
+         * The controller hasn't connected yet in this method, so calls to the controller
+         * (e.g. {@link #sendSessionCommand}) would be ignored. Override {@link #onPostConnect} for
+         * the custom initialization for the controller instead.
          *
          * @param session the session for this event
          * @param controller controller information.
@@ -763,6 +767,10 @@
         /**
          * Called immediately after a controller is connected. This is a convenient method to add
          * custom initialization between the session and a controller.
+         * <p>
+         * Note that calls to the controller (e.g. {@link #sendSessionCommand}) work here but don't
+         * work in {@link #onConnect} because the controller hasn't connected yet in
+         * {@link #onConnect}.
          *
          * @param session the session for this event
          * @param controller controller information.
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 91d2069..8051236 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -22,6 +22,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.media.audiopolicy.AudioMix;
@@ -2027,5 +2028,60 @@
          * The value is an {@code int}.
          */
         public static final String CHANNELS = MM_PREFIX + "channels";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The native channel mask.
+         * The value is a {@code long}.
+         * @hide
+         */
+        @TestApi
+        public static final String CHANNEL_MASK = MM_PREFIX + "channelMask";
+
+
+        /**
+         * Use for testing only. Do not expose.
+         * The port id of this input port in audioserver.
+         * The value is an {@code int}.
+         * @hide
+         */
+        @TestApi
+        public static final String PORT_ID = MM_PREFIX + "portId";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The buffer frameCount.
+         * The value is an {@code int}.
+         * @hide
+         */
+        @TestApi
+        public static final String FRAME_COUNT = MM_PREFIX + "frameCount";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The actual record track attributes used.
+         * The value is a {@code String}.
+         * @hide
+         */
+        @TestApi
+        public static final String ATTRIBUTES = MM_PREFIX + "attributes";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The buffer frameCount
+         * The value is a {@code double}.
+         * @hide
+         */
+        @TestApi
+        public static final String DURATION_MS = MM_PREFIX + "durationMs";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The number of times the record track has started
+         * The value is a {@code long}.
+         * @hide
+         */
+        @TestApi
+        public static final String START_COUNT = MM_PREFIX + "startCount";
     }
 }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index a15d322..09cfa95 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -22,6 +22,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Binder;
 import android.os.Build;
@@ -3624,5 +3625,59 @@
          */
         @Deprecated
         public static final String CHANNELMASK = "android.media.audiorecord.channelmask";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The current sample rate.
+         * The value is an {@code int}.
+         * @hide
+         */
+        @TestApi
+        public static final String SAMPLE_RATE = MM_PREFIX + "sampleRate";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The native channel mask.
+         * The value is a {@code long}.
+         * @hide
+         */
+        @TestApi
+        public static final String CHANNEL_MASK = MM_PREFIX + "channelMask";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The output audio data encoding.
+         * The value is a {@code String}.
+         * @hide
+         */
+        @TestApi
+        public static final String ENCODING = MM_PREFIX + "encoding";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The port id of this track port in audioserver.
+         * The value is an {@code int}.
+         * @hide
+         */
+        @TestApi
+        public static final String PORT_ID = MM_PREFIX + "portId";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The buffer frameCount.
+         * The value is an {@code int}.
+         * @hide
+         */
+        @TestApi
+        public static final String FRAME_COUNT = MM_PREFIX + "frameCount";
+
+        /**
+         * Use for testing only. Do not expose.
+         * The actual track attributes used.
+         * The value is a {@code String}.
+         * @hide
+         */
+        @TestApi
+        public static final String ATTRIBUTES = MM_PREFIX + "attributes";
     }
 }
diff --git a/native/android/choreographer.cpp b/native/android/choreographer.cpp
index 3fecd53..63e0734 100644
--- a/native/android/choreographer.cpp
+++ b/native/android/choreographer.cpp
@@ -37,6 +37,7 @@
 
 struct FrameCallback {
     AChoreographer_frameCallback callback;
+    AChoreographer_frameCallback64 callback64;
     void* data;
     nsecs_t dueTime;
 
@@ -50,8 +51,8 @@
 
 class Choreographer : public DisplayEventDispatcher, public MessageHandler {
 public:
-    void postFrameCallback(AChoreographer_frameCallback cb, void* data);
-    void postFrameCallbackDelayed(AChoreographer_frameCallback cb, void* data, nsecs_t delay);
+    void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
+                                  AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay);
 
     enum {
         MSG_SCHEDULE_CALLBACKS = 0,
@@ -107,14 +108,10 @@
     DisplayEventDispatcher(looper), mLooper(looper), mThreadId(std::this_thread::get_id()) {
 }
 
-void Choreographer::postFrameCallback(AChoreographer_frameCallback cb, void* data) {
-    postFrameCallbackDelayed(cb, data, 0);
-}
-
 void Choreographer::postFrameCallbackDelayed(
-        AChoreographer_frameCallback cb, void* data, nsecs_t delay) {
+        AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay) {
     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-    FrameCallback callback{cb, data, now + delay};
+    FrameCallback callback{cb, cb64, data, now + delay};
     {
         AutoMutex _l{mLock};
         mCallbacks.push(callback);
@@ -156,7 +153,11 @@
         }
     }
     for (const auto& cb : callbacks) {
-        cb.callback(timestamp, cb.data);
+        if (cb.callback64 != nullptr) {
+            cb.callback64(timestamp, cb.data);
+        } else if (cb.callback != nullptr) {
+            cb.callback(timestamp, cb.data);
+        }
     }
 }
 
@@ -204,10 +205,21 @@
 
 void AChoreographer_postFrameCallback(AChoreographer* choreographer,
         AChoreographer_frameCallback callback, void* data) {
-    AChoreographer_to_Choreographer(choreographer)->postFrameCallback(callback, data);
+    AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed(
+            callback, nullptr, data, 0);
 }
 void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
         AChoreographer_frameCallback callback, void* data, long delayMillis) {
     AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed(
-            callback, data, ms2ns(delayMillis));
+            callback, nullptr, data, ms2ns(delayMillis));
+}
+void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
+        AChoreographer_frameCallback64 callback, void* data) {
+    AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed(
+            nullptr, callback, data, 0);
+}
+void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
+        AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) {
+    AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed(
+            nullptr, callback, data, ms2ns(delayMillis));
 }
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index a3db2d6..e1dc406 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -21,6 +21,8 @@
     AChoreographer_getInstance; # introduced=24
     AChoreographer_postFrameCallback; # introduced=24
     AChoreographer_postFrameCallbackDelayed; # introduced=24
+    AChoreographer_postFrameCallback64; # introduced=29
+    AChoreographer_postFrameCallbackDelayed64; # introduced=29
     AConfiguration_copy;
     AConfiguration_delete;
     AConfiguration_diff;
diff --git a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
index efa4387..4a2d2fb 100644
--- a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
+++ b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
@@ -130,7 +130,6 @@
                 R.layout.navigation_bar_window, null);
         mCarNotificationWindow
                 .setBackgroundColor(mContext.getColor(R.color.notification_shade_background_color));
-
         inflateNotificationContent();
 
         WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
@@ -246,6 +245,12 @@
         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
             return distanceY > 0;
         }
+
+        @Override
+        public boolean onSingleTapUp(MotionEvent motionEvent) {
+            closeCarNotifications(DEFAULT_FLING_VELOCITY);
+            return false;
+        }
     }
 
     private class NotificationListTouchListener implements View.OnTouchListener {
@@ -324,6 +329,14 @@
         @Override
         public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX,
                 float distanceY) {
+            boolean isDown = event1.getY() - event2.getY() < 0;
+            // CarStatusBar and NavigationBar are identical so avoid the touch if it
+            // starts from NavigationBar to open.
+            if (event1.getRawY() > mCarNotificationWindow.getHeight() && isDown
+                    && mCarNotificationWindow.getVisibility() == View.GONE) {
+                mIsTracking = false;
+                return true;
+            }
             mIsTracking = true;
             mCarNotificationWindow.setVisibility(View.VISIBLE);
 
@@ -345,14 +358,15 @@
 
             boolean isUp = velocityY < 0;
             float distanceDelta = Math.abs(event1.getY() - event2.getY());
-
             if (isUp && distanceDelta > SWIPE_UP_MIN_DISTANCE) {
                 // fling up
                 mIsTracking = false;
                 closeCarNotifications(Math.abs(velocityY));
                 return true;
 
-            } else if (!isUp && distanceDelta > SWIPE_DOWN_MIN_DISTANCE) {
+            } else if (!isUp && distanceDelta > SWIPE_DOWN_MIN_DISTANCE
+                    && (event1.getRawY() < mCarNotificationWindow.getHeight()
+                    || mCarNotificationWindow.getVisibility() == View.VISIBLE)) {
                 // fling down
                 mIsTracking = false;
                 openCarNotifications(velocityY);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 4fc62bb..d9b4885 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -833,6 +833,11 @@
         return ssid;
     }
 
+    /**
+     * Returns the name associated with the stored config.
+     * @deprecated Please use {@link #getTitle()} instead to get the display name of an AccessPoint.
+     */
+    @Deprecated
     public String getConfigName() {
         if (mConfig != null && mConfig.isPasspoint()) {
             return mConfig.providerFriendlyName;
@@ -895,6 +900,8 @@
     public String getTitle() {
         if (isPasspoint()) {
             return mConfig.providerFriendlyName;
+        } else if (isPasspointConfig()) {
+            return mProviderFriendlyName;
         } else if (isOsuProvider()) {
             return mOsuProvider.getFriendlyName();
         } else {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 1fa7083..6269a71 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -232,7 +232,7 @@
      * Updates the title and summary; may indirectly call notifyChanged().
      */
     public void refresh() {
-        setTitle(this, mAccessPoint, mForSavedNetworks);
+        setTitle(this, mAccessPoint);
         final Context context = getContext();
         int level = mAccessPoint.getLevel();
         int wifiSpeed = mAccessPoint.getSpeed();
@@ -262,12 +262,8 @@
     }
 
     @VisibleForTesting
-    static void setTitle(AccessPointPreference preference, AccessPoint ap, boolean savedNetworks) {
-        if (savedNetworks) {
-            preference.setTitle(ap.getConfigName());
-        } else {
-            preference.setTitle(ap.getTitle());
-        }
+    static void setTitle(AccessPointPreference preference, AccessPoint ap) {
+        preference.setTitle(ap.getTitle());
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index a31d64c..fdc0fd3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -608,23 +608,23 @@
 
             // Log accesspoints that are being removed
             if (DBG()) {
-                Log.d(TAG, "------ Dumping SSIDs that were not seen on this scan ------");
+                Log.d(TAG,
+                        "------ Dumping AccessPoints that were not seen on this scan ------");
                 for (AccessPoint prevAccessPoint : mInternalAccessPoints) {
-                    if (prevAccessPoint.getSsid() == null)
-                        continue;
-                    String prevSsid = prevAccessPoint.getSsidStr();
+                    String prevTitle = prevAccessPoint.getTitle();
                     boolean found = false;
                     for (AccessPoint newAccessPoint : accessPoints) {
-                        if (newAccessPoint.getSsidStr() != null && newAccessPoint.getSsidStr()
-                                .equals(prevSsid)) {
+                        if (newAccessPoint.getTitle() != null && newAccessPoint.getTitle()
+                                .equals(prevTitle)) {
                             found = true;
                             break;
                         }
                     }
                     if (!found)
-                        Log.d(TAG, "Did not find " + prevSsid + " in this scan");
+                        Log.d(TAG, "Did not find " + prevTitle + " in this scan");
                 }
-                Log.d(TAG, "---- Done dumping SSIDs that were not seen on this scan ----");
+                Log.d(TAG,
+                        "---- Done dumping AccessPoints that were not seen on this scan ----");
             }
 
             mInternalAccessPoints.clear();
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 06f5fde..7c367c7 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -713,7 +713,7 @@
                 .setProviderFriendlyName(providerFriendlyName).build();
         assertThat(ap.isPasspointConfig()).isTrue();
         assertThat(ap.getPasspointFqdn()).isEqualTo(fqdn);
-        assertThat(ap.getConfigName()).isEqualTo(providerFriendlyName);
+        assertThat(ap.getTitle()).isEqualTo(providerFriendlyName);
     }
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
index c5cbea7..21aa526 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
@@ -98,7 +98,7 @@
                 .build();
         final AccessPointPreference preference = mock(AccessPointPreference.class);
 
-        AccessPointPreference.setTitle(preference, ap, false /* savedNetwork */);
+        AccessPointPreference.setTitle(preference, ap);
         verify(preference).setTitle(ssid);
     }
 }
diff --git a/packages/SystemUI/res/layout/assistant_handle.xml b/packages/SystemUI/res/layout/assistant_handle.xml
new file mode 100644
index 0000000..a952ca5
--- /dev/null
+++ b/packages/SystemUI/res/layout/assistant_handle.xml
@@ -0,0 +1,25 @@
+<?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
+  -->
+
+<com.android.systemui.statusbar.phone.NavigationHandle
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/assistant_handle"
+    android:layout_width="@dimen/navigation_assistant_handle_width"
+    android:layout_height="match_parent"
+    android:layout_weight="0"
+/>
+
diff --git a/packages/SystemUI/res/layout/home_handle.xml b/packages/SystemUI/res/layout/home_handle.xml
index 48ea5c4..d950f39 100644
--- a/packages/SystemUI/res/layout/home_handle.xml
+++ b/packages/SystemUI/res/layout/home_handle.xml
@@ -18,7 +18,7 @@
 <com.android.systemui.statusbar.phone.NavigationHandle
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/home_handle"
-    android:layout_width="@dimen/navigation_handle_width"
+    android:layout_width="@dimen/navigation_home_handle_width"
     android:layout_height="match_parent"
     android:layout_weight="0"
     />
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1d56680..121cdd8 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -326,7 +326,7 @@
     <!-- Nav bar button default ordering/layout -->
     <string name="config_navBarLayout" translatable="false">left[.5W],back[1WC];home;recent[1WC],right[.5W]</string>
     <string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]</string>
-    <string name="config_navBarLayoutHandle" translatable="false">";home_handle;"</string>
+    <string name="config_navBarLayoutHandle" translatable="false">";home_handle;assistant_handle[.18WC]"</string>
 
     <bool name="quick_settings_show_full_alarm">false</bool>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9a2eb94..4457440 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -34,9 +34,11 @@
     <dimen name="navigation_bar_deadzone_size_max">32dp</dimen>
 
     <!-- dimensions for the navigation bar handle -->
-    <dimen name="navigation_handle_width">180dp</dimen>
     <dimen name="navigation_handle_radius">2dp</dimen>
     <dimen name="navigation_handle_bottom">8dp</dimen>
+    <dimen name="navigation_handle_horizontal_margin">30dp</dimen>
+    <dimen name="navigation_home_handle_width">180dp</dimen>
+    <dimen name="navigation_assistant_handle_width">36dp</dimen>
 
     <!-- Height of notification icons in the status bar -->
     <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 37abab9..ce615b6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -113,4 +113,10 @@
      * Sent when there was an action on one of the onboarding tips view.
      */
     void onTip(int actionType, int viewType) = 10;
+
+    /**
+     * Sent when device assistant changes its default assistant whether it is available or not.
+     */
+    void onAssistantAvailable(boolean available) = 13;
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 83398cf..ff68d2b 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -315,8 +315,13 @@
     }
 
     @Nullable
+    public ComponentName getAssistInfoForUser(int userId) {
+        return mAssistUtils.getAssistComponentForUser(userId);
+    }
+
+    @Nullable
     private ComponentName getAssistInfo() {
-        return mAssistUtils.getAssistComponentForUser(KeyguardUpdateMonitor.getCurrentUser());
+        return getAssistInfoForUser(KeyguardUpdateMonitor.getCurrentUser());
     }
 
     public void showDisclosure() {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 4addbb5..25ee87a 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -528,7 +528,9 @@
     /**
      * Removes and releases an ActivityView if one was previously created for this bubble.
      */
-    public void destroyActivityView() {
+    public void cleanUpExpandedState() {
+        removeView(mNotifRow);
+
         if (mActivityView == null) {
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 8f9f1cb..97aa786 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -385,7 +385,7 @@
 
         // Remove it from the views
         int removedIndex = mBubbleContainer.indexOfChild(b.iconView);
-        b.expandedView.destroyActivityView();
+        b.expandedView.cleanUpExpandedState();
         mBubbleContainer.removeView(b.iconView);
 
         int bubbleCount = mBubbleContainer.getChildCount();
@@ -414,7 +414,7 @@
     public void stackDismissed() {
         for (Bubble bubble : mBubbleData.getBubbles()) {
             bubble.entry.setBubbleDismissed(true);
-            bubble.expandedView.destroyActivityView();
+            bubble.expandedView.cleanUpExpandedState();
         }
         mBubbleData.clear();
         collapseStack();
@@ -495,7 +495,7 @@
     }
 
     /**
-     * Expands the stack fo bubbles.
+     * Expands the stack of bubbles.
      * <p>
      * Must be called from the main thread.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 3fc60cd..b68c7c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -51,10 +51,12 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -137,6 +139,7 @@
     private AccessibilityManager mAccessibilityManager;
     private MagnificationContentObserver mMagnificationObserver;
     private ContentResolver mContentResolver;
+    private boolean mAssistantAvailable;
 
     private int mDisabledFlags1;
     private int mDisabledFlags2;
@@ -167,6 +170,11 @@
         public void onConnectionChanged(boolean isConnected) {
             mNavigationBarView.updateStates();
             updateScreenPinningGestures();
+
+            // Send the assistant availability upon connection
+            if (isConnected) {
+                mNavigationBarView.setAssistantAvailable(mAssistantAvailable);
+            }
         }
 
         @Override
@@ -213,6 +221,19 @@
 
     private final Runnable mAutoDim = () -> getBarTransitions().setAutoDim(true);
 
+    private final ContentObserver mAssistContentObserver = new ContentObserver(
+            new Handler(Looper.getMainLooper())) {
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            boolean available = mAssistManager
+                    .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
+            if (mAssistantAvailable != available) {
+                mNavigationBarView.setAssistantAvailable(available);
+                mAssistantAvailable = available;
+            }
+        }
+    };
+
     @Inject
     public NavigationBarFragment(AccessibilityManagerWrapper accessibilityManagerWrapper,
             DeviceProvisionedController deviceProvisionedController, MetricsLogger metricsLogger,
@@ -221,6 +242,7 @@
         mDeviceProvisionedController = deviceProvisionedController;
         mMetricsLogger = metricsLogger;
         mAssistManager = assistManager;
+        mAssistantAvailable = mAssistManager.getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
         mOverviewProxyService = overviewProxyService;
     }
 
@@ -242,6 +264,9 @@
         mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED), false,
                 mMagnificationObserver, UserHandle.USER_ALL);
+        mContentResolver.registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
+                false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
 
         if (savedInstanceState != null) {
             mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
@@ -258,6 +283,7 @@
         super.onDestroy();
         mAccessibilityManagerWrapper.removeCallback(mAccessibilityListener);
         mContentResolver.unregisterContentObserver(mMagnificationObserver);
+        mContentResolver.unregisterContentObserver(mAssistContentObserver);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index faa2ab1..2a38f77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -63,6 +63,7 @@
     public static final String NAVSPACE = "space";
     public static final String CLIPBOARD = "clipboard";
     public static final String HOME_HANDLE = "home_handle";
+    public static final String ASSISTANT_HANDLE = "assistant_handle";
     public static final String KEY = "key";
     public static final String LEFT = "left";
     public static final String RIGHT = "right";
@@ -398,6 +399,8 @@
             v = inflater.inflate(R.layout.contextual, parent, false);
         } else if (HOME_HANDLE.equals(button)) {
             v = inflater.inflate(R.layout.home_handle, parent, false);
+        } else if (ASSISTANT_HANDLE.equals(button)) {
+            v = inflater.inflate(R.layout.assistant_handle, parent, false);
         } else if (button.startsWith(KEY)) {
             String uri = extractImage(button);
             int code = extractKeycode(button);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index f82b05e..c389082 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -171,6 +171,7 @@
     private NotificationPanelView mPanelView;
 
     private NavBarTintController mColorAdaptionController;
+    private boolean mAssistantAvailable;
     private NavigationPrototypeController mPrototypeController;
     private NavigationGestureAction[] mDefaultGestureMap;
     private QuickScrubAction mQuickScrubAction;
@@ -347,6 +348,11 @@
         public void onHomeHandleVisiblilityChanged(boolean visible) {
             showHomeHandle(visible);
         }
+
+        @Override
+        public void onAssistantGestureEnabled(boolean enabled) {
+            updateAssistantAvailability();
+        }
     };
 
     public NavigationBarView(Context context, AttributeSet attrs) {
@@ -385,6 +391,7 @@
         mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
         mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
         mButtonDispatchers.put(R.id.home_handle, new ButtonDispatcher(R.id.home_handle));
+        mButtonDispatchers.put(R.id.assistant_handle, new ButtonDispatcher(R.id.assistant_handle));
         mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
         mButtonDispatchers.put(R.id.menu, menuButton);
         mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
@@ -582,6 +589,10 @@
         return mButtonDispatchers.get(R.id.home_handle);
     }
 
+    public ButtonDispatcher getAssistantHandle() {
+        return mButtonDispatchers.get(R.id.assistant_handle);
+    }
+
     public SparseArray<ButtonDispatcher> getButtonDispatchers() {
         return mButtonDispatchers;
     }
@@ -940,6 +951,24 @@
         }
     }
 
+    public void setAssistantAvailable(boolean available) {
+        mAssistantAvailable = available;
+        updateAssistantAvailability();
+    }
+
+    // TODO(b/112934365): move this back to NavigationBarFragment when prototype is removed
+    private void updateAssistantAvailability() {
+        boolean available = mAssistantAvailable && mPrototypeController.isAssistantGestureEnabled();
+        getAssistantHandle().setVisibility(available ? View.VISIBLE : View.GONE);
+        if (mOverviewProxyService.getProxy() != null) {
+            try {
+                mOverviewProxyService.getProxy().onAssistantAvailable(available);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Unable to send assistant availability data to launcher");
+            }
+        }
+    }
+
     public void setMenuVisibility(final boolean show) {
         mContextualButtonGroup.setButtonVisiblity(R.id.menu, show);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
index 2c31e2c..31579c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
@@ -43,6 +43,7 @@
     private final String GESTURE_MATCH_SETTING = "quickstepcontroller_gesture_match_map";
     public static final String NAV_COLOR_ADAPT_ENABLE_SETTING = "navbar_color_adapt_enable";
     public static final String SHOW_HOME_HANDLE_SETTING = "quickstepcontroller_showhandle";
+    public static final String ENABLE_ASSISTANT_GESTURE = "ENABLE_ASSISTANT_GESTURE";
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({ACTION_DEFAULT, ACTION_QUICKSTEP, ACTION_QUICKSCRUB, ACTION_BACK,
@@ -87,6 +88,7 @@
         registerObserver(NAV_COLOR_ADAPT_ENABLE_SETTING);
         registerObserver(EDGE_SENSITIVITY_WIDTH_SETTING);
         registerObserver(SHOW_HOME_HANDLE_SETTING);
+        registerObserver(ENABLE_ASSISTANT_GESTURE);
     }
 
     /**
@@ -119,6 +121,8 @@
                         getEdgeSensitivityHeight());
             } else if (path.endsWith(SHOW_HOME_HANDLE_SETTING)) {
                 mListener.onHomeHandleVisiblilityChanged(showHomeHandle());
+            } else if (path.endsWith(ENABLE_ASSISTANT_GESTURE)) {
+                mListener.onAssistantGestureEnabled(isAssistantGestureEnabled());
             }
         }
     }
@@ -162,6 +166,11 @@
         return getGlobalBool(SHOW_HOME_HANDLE_SETTING, false /* default */);
     }
 
+    boolean isAssistantGestureEnabled() {
+        return getGlobalBool(ENABLE_ASSISTANT_GESTURE, false /* default */);
+    }
+
+
     /**
      * Since Settings.Global cannot pass arrays, use a string to represent each character as a
      * gesture map to actions corresponding to {@see GestureAction}. The number is represented as:
@@ -201,5 +210,6 @@
         void onHomeHandleVisiblilityChanged(boolean visible);
         void onColorAdaptChanged(boolean enabled);
         void onEdgeSensitivityChanged(int width, int height);
+        void onAssistantGestureEnabled(boolean enabled);
     }
 }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 245e2c9..0e852f8 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -479,13 +479,16 @@
 
     private void setDeviceConfigProperties() {
         synchronized (mLock) {
-            mAugmentedServiceIdleUnbindTimeoutMs = Helper.getIntDeviceConfigProperty(
+            mAugmentedServiceIdleUnbindTimeoutMs = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_AUTOFILL,
                     AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT,
                     (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
-            mAugmentedServiceRequestTimeoutMs = Helper.getIntDeviceConfigProperty(
+            mAugmentedServiceRequestTimeoutMs = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_AUTOFILL,
                     AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT,
                     DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS);
-            mSupportedSmartSuggestionModes = Helper.getIntDeviceConfigProperty(
+            mSupportedSmartSuggestionModes = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_AUTOFILL,
                     AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES,
                     AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM);
             if (verbose) {
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index d300bf2..3c0da7d 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -22,11 +22,9 @@
 import android.app.assist.AssistStructure.ViewNode;
 import android.content.ComponentName;
 import android.metrics.LogMaker;
-import android.provider.DeviceConfig;
 import android.service.autofill.Dataset;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.Log;
 import android.util.Slog;
 import android.view.WindowManager;
 import android.view.autofill.AutofillId;
@@ -207,21 +205,6 @@
         }
     }
 
-    /**
-     * Gets the value of a device config property from the Autofill namespace.
-     */
-    static int getIntDeviceConfigProperty(@NonNull String key, int defaultValue) {
-        final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_AUTOFILL, key);
-        if (value == null) return defaultValue;
-
-        try {
-            return Integer.parseInt(value);
-        } catch (Exception e) {
-            Log.w(TAG, "error parsing value (" + value + ") of property " + key + ": " + e);
-            return defaultValue;
-        }
-    }
-
     private interface ViewNodeFilter {
         boolean matches(ViewNode node);
     }
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 0205ad8..c75b4c6 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -234,18 +234,23 @@
 
     private void setFineTuneParamsFromDeviceConfig() {
         synchronized (mLock) {
-            mDevCfgMaxBufferSize = ContentCaptureHelper.getIntDeviceConfigProperty(
+            mDevCfgMaxBufferSize = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                     ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
                     ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE);
-            mDevCfgIdleFlushingFrequencyMs = ContentCaptureHelper.getIntDeviceConfigProperty(
+            mDevCfgIdleFlushingFrequencyMs = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                     ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY,
                     ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS);
-            mDevCfgTextChangeFlushingFrequencyMs = ContentCaptureHelper.getIntDeviceConfigProperty(
+            mDevCfgTextChangeFlushingFrequencyMs = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                     ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY,
                     ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS);
-            mDevCfgLogHistorySize = ContentCaptureHelper.getIntDeviceConfigProperty(
+            mDevCfgLogHistorySize = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                     ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 20);
-            mDevCfgIdleUnbindTimeoutMs = ContentCaptureHelper.getIntDeviceConfigProperty(
+            mDevCfgIdleUnbindTimeoutMs = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                     ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
                     (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
             if (verbose) {
@@ -260,7 +265,8 @@
     }
 
     private void setLoggingLevelFromDeviceConfig() {
-        mDevCfgLoggingLevel = ContentCaptureHelper.getIntDeviceConfigProperty(
+        mDevCfgLoggingLevel = DeviceConfig.getInt(
+                DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
                 ContentCaptureHelper.getDefaultLoggingLevel());
         ContentCaptureHelper.setLoggingLevel(mDevCfgLoggingLevel);
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 0603154..feb1ac1 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -177,10 +177,8 @@
 
     @Override // from ContentCaptureServiceCallbacks
     public void onServiceDied(@NonNull RemoteContentCaptureService service) {
-        if (mMaster.debug) Slog.d(TAG, "remote service died: " + service);
-        synchronized (mLock) {
-            removeSelfFromCacheLocked();
-        }
+        // Don't do anything; eventually the system will bind to it again...
+        Slog.w(TAG, "remote service died: " + service);
     }
 
     // TODO(b/119613670): log metrics
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 219e046..199477c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -71,6 +71,7 @@
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
 import android.net.InetAddresses;
 import android.net.IpPrefix;
 import android.net.LinkProperties;
@@ -3798,6 +3799,22 @@
         mTethering.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
     }
 
+    /** Register tethering event callback. */
+    @Override
+    public void registerTetheringEventCallback(ITetheringEventCallback callback,
+            String callerPkg) {
+        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
+        mTethering.registerTetheringEventCallback(callback);
+    }
+
+    /** Unregister tethering event callback. */
+    @Override
+    public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
+            String callerPkg) {
+        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
+        mTethering.unregisterTetheringEventCallback(callback);
+    }
+
     // Called when we lose the default network and have no replacement yet.
     // This will automatically be cleared after X seconds or a new default network
     // becomes CONNECTED, whichever happens first.  The timer is started by the
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 6b66394..3ab3c34 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1132,7 +1132,7 @@
                         KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
                 NOTIFICATION_WHITELIST_DURATION = mParser.getDurationMillis(
                         KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L);
-                WAIT_FOR_UNLOCK = mParser.getBoolean(KEY_WAIT_FOR_UNLOCK, false);
+                WAIT_FOR_UNLOCK = mParser.getBoolean(KEY_WAIT_FOR_UNLOCK, true);
                 PRE_IDLE_FACTOR_LONG = mParser.getFloat(KEY_PRE_IDLE_FACTOR_LONG, 1.67f);
                 PRE_IDLE_FACTOR_SHORT = mParser.getFloat(KEY_PRE_IDLE_FACTOR_SHORT, 0.33f);
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f98327b..0a80d45 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3969,11 +3969,12 @@
         final long callingId = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
-                mProcessList.killAllBackgroundProcessesLocked();
-
+                // Allow memory level to go down (the flag needs to be set before updating oom adj)
+                // because this method is also used to simulate low memory.
                 mAllowLowerMemLevel = true;
+                mProcessList.killPackageProcessesLocked(null /* packageName */, -1 /* appId */,
+                        UserHandle.USER_ALL, ProcessList.CACHED_APP_MIN_ADJ, "kill all background");
 
-                updateOomAdjLocked();
                 doLowMemReportIfNeededLocked(null);
             }
         } finally {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 4f6f9fd..85322d6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -492,7 +492,6 @@
             final long endTime = SystemClock.uptimeMillis();
             PrintWriter out = mWaitOption ? pw : getErrPrintWriter();
             boolean launched = false;
-            boolean hotLaunch = false;
             switch (res) {
                 case ActivityManager.START_SUCCESS:
                     launched = true;
@@ -518,8 +517,6 @@
                     break;
                 case ActivityManager.START_TASK_TO_FRONT:
                     launched = true;
-                    //TODO(b/120981435) remove special case
-                    hotLaunch = true;
                     out.println(
                             "Warning: Activity not started, its current "
                                     + "task has been brought to the front");
@@ -567,9 +564,7 @@
                     result.who = intent.getComponent();
                 }
                 pw.println("Status: " + (result.timeout ? "timeout" : "ok"));
-                final @WaitResult.LaunchState int launchState =
-                        hotLaunch ? WaitResult.LAUNCH_STATE_HOT : result.launchState;
-                pw.println("LaunchState: " + launchStateToString(launchState));
+                pw.println("LaunchState: " + launchStateToString(result.launchState));
                 if (result.who != null) {
                     pw.println("Activity: " + result.who.flattenToShortString());
                 }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 620fb2c..d02fd73 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2085,25 +2085,6 @@
         }
     }
 
-    void killAllBackgroundProcessesLocked() {
-        final ArrayList<ProcessRecord> procs = new ArrayList<>();
-        final int NP = mProcessNames.getMap().size();
-        for (int ip = 0; ip < NP; ip++) {
-            final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
-            final int NA = apps.size();
-            for (int ia = 0; ia < NA; ia++) {
-                final ProcessRecord app = apps.valueAt(ia);
-                if (app.isPersistent()) {
-                    // We don't kill persistent processes.
-                    continue;
-                }
-                if (app.removed || app.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
-                    procs.add(app);
-                }
-            }
-        }
-    }
-
     @GuardedBy("mService")
     boolean killPackageProcessesLocked(String packageName, int appId, int userId, int minOomAdj,
             String reason) {
@@ -2140,6 +2121,11 @@
 
                 // Skip process if it doesn't meet our oom adj requirement.
                 if (app.setAdj < minOomAdj) {
+                    // Note it is still possible to have a process with oom adj 0 in the killed
+                    // processes, but it does not mean misjudgment. E.g. a bound service process
+                    // and its client activity process are both in the background, so they are
+                    // collected to be killed. If the client activity is killed first, the service
+                    // may be scheduled to unbind and become an executing service (oom adj 0).
                     continue;
                 }
 
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 47c9b86..5965d59 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -127,8 +127,7 @@
     }
 
     private boolean isServiceEnabled() {
-        final String enabled = DeviceConfig.getProperty(NAMESPACE, SERVICE_ENABLED);
-        return enabled == null ? DEFAULT_SERVICE_ENABLED : "true".equals(enabled);
+        return DeviceConfig.getBoolean(NAMESPACE, SERVICE_ENABLED, DEFAULT_SERVICE_ENABLED);
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 3b4b6f8..35704d40 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -62,6 +62,7 @@
 import android.hardware.usb.UsbManager;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
@@ -82,6 +83,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
@@ -184,6 +186,9 @@
     private final VersionedBroadcastListener mDefaultSubscriptionChange;
     private final TetheringDependencies mDeps;
     private final EntitlementManager mEntitlementMgr;
+    private final Handler mHandler;
+    private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
+            new RemoteCallbackList<>();
 
     private volatile TetheringConfiguration mConfig;
     private InterfaceSet mCurrentUpstreamIfaceSet;
@@ -193,6 +198,7 @@
     private boolean mRndisEnabled;       // track the RNDIS function enabled state
     // True iff. WiFi tethering should be started when soft AP is ready.
     private boolean mWifiTetherRequested;
+    private Network mTetherUpstream;
 
     public Tethering(Context context, INetworkManagementService nmService,
             INetworkStatsService statsService, INetworkPolicyManager policyManager,
@@ -213,9 +219,9 @@
         mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps);
         mTetherMasterSM.start();
 
-        final Handler smHandler = mTetherMasterSM.getHandler();
-        mOffloadController = new OffloadController(smHandler,
-                mDeps.getOffloadHardwareInterface(smHandler, mLog),
+        mHandler = mTetherMasterSM.getHandler();
+        mOffloadController = new OffloadController(mHandler,
+                mDeps.getOffloadHardwareInterface(mHandler, mLog),
                 mContext.getContentResolver(), mNMService,
                 mLog);
         mUpstreamNetworkMonitor = deps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
@@ -227,7 +233,7 @@
         mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM,
                 mLog, systemProperties);
         mCarrierConfigChange = new VersionedBroadcastListener(
-                "CarrierConfigChangeListener", mContext, smHandler, filter,
+                "CarrierConfigChangeListener", mContext, mHandler, filter,
                 (Intent ignored) -> {
                     mLog.log("OBSERVED carrier config change");
                     updateConfiguration();
@@ -237,7 +243,7 @@
         filter = new IntentFilter();
         filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
         mDefaultSubscriptionChange = new VersionedBroadcastListener(
-                "DefaultSubscriptionChangeListener", mContext, smHandler, filter,
+                "DefaultSubscriptionChangeListener", mContext, mHandler, filter,
                 (Intent ignored) -> {
                     mLog.log("OBSERVED default data subscription change");
                     updateConfiguration();
@@ -248,14 +254,13 @@
         // Load tethering configuration.
         updateConfiguration();
 
-        startStateMachineUpdaters();
+        startStateMachineUpdaters(mHandler);
     }
 
-    private void startStateMachineUpdaters() {
+    private void startStateMachineUpdaters(Handler handler) {
         mCarrierConfigChange.startListening();
         mDefaultSubscriptionChange.startListening();
 
-        final Handler handler = mTetherMasterSM.getHandler();
         IntentFilter filter = new IntentFilter();
         filter.addAction(UsbManager.ACTION_USB_STATE);
         filter.addAction(CONNECTIVITY_ACTION);
@@ -1229,8 +1234,13 @@
                     sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
                 }
             }
-            mUpstreamNetworkMonitor.setCurrentUpstream((ns != null) ? ns.network : null);
             setUpstreamNetwork(ns);
+            final Network newUpstream = (ns != null) ? ns.network : null;
+            if (mTetherUpstream != newUpstream) {
+                mTetherUpstream = newUpstream;
+                mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream);
+                reportUpstreamChanged(mTetherUpstream);
+            }
         }
 
         protected void setUpstreamNetwork(NetworkState ns) {
@@ -1413,6 +1423,10 @@
                 mUpstreamNetworkMonitor.stop();
                 notifyDownstreamsOfNewUpstreamIface(null);
                 handleNewUpstreamNetworkState(null);
+                if (mTetherUpstream != null) {
+                    mTetherUpstream = null;
+                    reportUpstreamChanged(null);
+                }
             }
 
             private boolean updateUpstreamWanted() {
@@ -1684,6 +1698,40 @@
         }
     }
 
+    /** Register tethering event callback */
+    public void registerTetheringEventCallback(ITetheringEventCallback callback) {
+        mHandler.post(() -> {
+            try {
+                callback.onUpstreamChanged(mTetherUpstream);
+            } catch (RemoteException e) {
+                // Not really very much to do here.
+            }
+            mTetheringEventCallbacks.register(callback);
+        });
+    }
+
+    /** Unregister tethering event callback */
+    public void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
+        mHandler.post(() -> {
+            mTetheringEventCallbacks.unregister(callback);
+        });
+    }
+
+    private void reportUpstreamChanged(Network network) {
+        final int length = mTetheringEventCallbacks.beginBroadcast();
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network);
+                } catch (RemoteException e) {
+                    // Not really very much to do here.
+                }
+            }
+        } finally {
+            mTetheringEventCallbacks.finishBroadcast();
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         // Binder.java closes the resource for us.
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index b4a93d3..3052330 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -953,11 +953,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
-            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
-                hideInputMethodMenu();
-                // No need to update mIsInteractive
-                return;
-            } else if (Intent.ACTION_USER_ADDED.equals(action)
+            if (Intent.ACTION_USER_ADDED.equals(action)
                     || Intent.ACTION_USER_REMOVED.equals(action)) {
                 updateCurrentProfileIds();
                 return;
@@ -1549,12 +1545,35 @@
                 mSettingsObserver.registerContentObserverLocked(currentUserId);
 
                 final IntentFilter broadcastFilter = new IntentFilter();
-                broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
                 broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
                 broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
                 broadcastFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
                 broadcastFilter.addAction(ACTION_SHOW_INPUT_METHOD_PICKER);
                 mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
+                mContext.registerReceiverAsUser(
+                        new BroadcastReceiver() {
+                            @Override
+                            public void onReceive(Context context, Intent intent) {
+                                // Intent is guaranteed to be ACTION_CLOSE_SYSTEM_DIALOGS here.
+                                final PendingResult pendingResult = getPendingResult();
+                                if (pendingResult == null) {
+                                    return;
+                                }
+                                // sender userId can be a real user ID or USER_ALL.
+                                final int senderUserId = pendingResult.getSendingUserId();
+                                if (senderUserId != UserHandle.USER_ALL) {
+                                    final int resolvedUserId = PER_PROFILE_IME_ENABLED
+                                            ? senderUserId
+                                            : mUserManagerInternal.getProfileParentId(senderUserId);
+                                    if (resolvedUserId != mSettings.getCurrentUserId()) {
+                                        // A background user is trying to hide the dialog. Ignore.
+                                        return;
+                                    }
+                                }
+                                hideInputMethodMenu();
+                            }
+                        }, UserHandle.ALL, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS),
+                        null, null);
 
                 final String defaultImiId = mSettings.getSelectedInputMethod();
                 final boolean imeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9281bf8..d25360a 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2477,29 +2477,27 @@
             checkCallerIsSameApp(callingPkg);
             final int callingUid = Binder.getCallingUid();
             UserHandle user = UserHandle.getUserHandleForUid(callingUid);
-            try {
-                ApplicationInfo info =
-                        mPackageManager.getApplicationInfo(delegate,
-                                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
-                                user.getIdentifier());
-                if (info != null) {
-                    mPreferencesHelper.setNotificationDelegate(
-                            callingPkg, callingUid, delegate, info.uid);
-                    handleSavePolicyFile();
+            if (delegate == null) {
+                mPreferencesHelper.revokeNotificationDelegate(callingPkg, Binder.getCallingUid());
+                handleSavePolicyFile();
+            } else {
+                try {
+                    ApplicationInfo info =
+                            mPackageManager.getApplicationInfo(delegate,
+                                    MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                                    user.getIdentifier());
+                    if (info != null) {
+                        mPreferencesHelper.setNotificationDelegate(
+                                callingPkg, callingUid, delegate, info.uid);
+                        handleSavePolicyFile();
+                    }
+                } catch (RemoteException e) {
+                    e.rethrowFromSystemServer();
                 }
-            } catch (RemoteException e) {
-                // :(
             }
         }
 
         @Override
-        public void revokeNotificationDelegate(String callingPkg) {
-            checkCallerIsSameApp(callingPkg);
-            mPreferencesHelper.revokeNotificationDelegate(callingPkg, Binder.getCallingUid());
-            handleSavePolicyFile();
-        }
-
-        @Override
         public String getNotificationDelegate(String callingPkg) {
             // callable by Settings also
             checkCallerIsSystemOrSameApp(callingPkg);
@@ -7196,7 +7194,7 @@
 
         @Override
         protected String getRequiredPermission() {
-            // only signature/privileged apps can be bound
+            // only signature/privileged apps can be bound.
             return android.Manifest.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE;
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a3b72fd..3a4bcca 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -482,9 +482,9 @@
         }
 
         if (callingUid == Process.SYSTEM_UID) {
-            params.installFlags |= PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE;
+            params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
         } else {
-            params.installFlags &= ~PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE;
+            params.installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE;
         }
 
         boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index ff81ad5..a12005b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -820,9 +820,9 @@
         // platform builds.
         //
         // In case of user builds, downgrade is permitted only for the system server initiated
-        // sessions. This is enforced by INSTALL_RESPECT_ALLOW_DOWNGRADE flag parameter.
+        // sessions. This is enforced by INSTALL_ALLOW_DOWNGRADE flag parameter.
         final boolean downgradeRequested =
-                (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
+                (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0;
         if (!downgradeRequested) {
             return false;
         }
@@ -832,7 +832,7 @@
         if (isDebuggable) {
             return true;
         }
-        return (installFlags & PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE) != 0;
+        return (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 114810d..912a50e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2337,7 +2337,7 @@
                     sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;
                     break;
                 case "-d":
-                    sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
+                    sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
                     break;
                 case "-g":
                     sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index d3e1a05..ffdfe57 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -356,7 +356,7 @@
             PackageInstaller packageInstaller = pm.getPackageInstaller();
             PackageInstaller.SessionParams parentParams = new PackageInstaller.SessionParams(
                     PackageInstaller.SessionParams.MODE_FULL_INSTALL);
-            parentParams.setAllowDowngrade(true);
+            parentParams.setRequestDowngrade(true);
             parentParams.setMultiPackage();
             if (data.isStaged()) {
                 parentParams.setStaged();
@@ -377,7 +377,7 @@
                         params.setInstallerPackageName(installerPackageName);
                     }
                 }
-                params.setAllowDowngrade(true);
+                params.setRequestDowngrade(true);
                 if (data.isStaged()) {
                     params.setStaged();
                 }
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 23bed7b..5a746eb 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -27,6 +27,8 @@
 import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
 import static android.app.ActivityManager.START_SUCCESS;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.WaitResult.LAUNCH_STATE_COLD;
+import static android.app.WaitResult.LAUNCH_STATE_HOT;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -1311,6 +1313,8 @@
                         break;
                     }
                     case START_TASK_TO_FRONT: {
+                        outResult.launchState =
+                                r.attachedToProcess() ? LAUNCH_STATE_HOT : LAUNCH_STATE_COLD;
                         // ActivityRecord may represent a different activity, but it should not be
                         // in the resumed state.
                         if (r.nowVisible && r.isState(RESUMED)) {
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index fae7920..07ffaac 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -322,6 +322,7 @@
      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
      *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  <code>RESULT_ERROR_NO_SERVICE</code><br>
      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
      *  the extra "errorCode" containing a radio technology specific value,
      *  generally only useful for troubleshooting.<br>
@@ -371,19 +372,12 @@
         if (DBG) {
             Log.d(TAG, "for subId: " + subId + ", subscription-info: " + info);
         }
-        if (info == null) {
-            // There is no subscription for the given subId. That can only mean one thing:
-            // the caller is using a SmsManager instance with an obsolete subscription id.
-            // That is most probably because caller didn't invalidate SmsManager instance
-            // for an already deleted subscription id.
-            Log.e(TAG, "subId: " + subId + " for this SmsManager instance is obsolete.");
-            sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_NO_SERVICE);
-        }
 
         /* If the Subscription associated with this SmsManager instance belongs to a remote-sim,
          * then send the message thru the remote-sim subscription.
          */
-        if (info.getSubscriptionType() == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) {
+        if (info != null
+                && info.getSubscriptionType() == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) {
             if (DBG) Log.d(TAG, "sending message thru bluetooth");
             sendTextMessageBluetooth(destinationAddress, scAddress, text, sentIntent,
                     deliveryIntent, info);
@@ -391,8 +385,10 @@
         }
 
         try {
+            // If the subscription is invalid or default, we will use the default phone to send the
+            // SMS and possibly fail later in the SMS sending process.
             ISms iccISms = getISmsServiceOrThrow();
-            iccISms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
+            iccISms.sendTextForSubscriber(subId, ActivityThread.currentPackageName(),
                     destinationAddress,
                     scAddress, text, sentIntent, deliveryIntent,
                     persistMessage);
@@ -465,6 +461,9 @@
     }
 
     private void sendErrorInPendingIntent(PendingIntent intent, int errorCode) {
+        if (intent == null) {
+            return;
+        }
         try {
             intent.send(errorCode);
         } catch (PendingIntent.CanceledException e) {
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 9104d9f..d12cda8 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -154,7 +154,7 @@
          * @param item the IMS provisioning key constant, as defined by the OEM.
          * @param value the new String value of the IMS configuration constant.
          */
-        public void onProvisioningStringChanged(int item, String value) {
+        public void onProvisioningStringChanged(int item, @NonNull String value) {
             // Base Implementation
         }
 
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index ae6cd29..a95b6f1 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -577,9 +577,14 @@
     }
 
     @Override
-    public boolean bindIsolatedService(Intent service,
-            ServiceConnection conn, int flags,
-            String instanceName) {
+    public boolean bindService(Intent service, int flags, Executor executor,
+            ServiceConnection conn) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean bindIsolatedService(Intent service, int flags, String instanceName,
+            Executor executor, ServiceConnection conn) {
         throw new UnsupportedOperationException();
     }
 
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index 73db451..dd4a9a3 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -17,13 +17,13 @@
 package android.test;
 
 import android.accounts.AccountManager;
-import android.content.ContextWrapper;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.content.Context;
-import android.content.ServiceConnection;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.test.mock.MockAccountManager;
@@ -31,6 +31,7 @@
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 
 /**
@@ -75,8 +76,14 @@
     }
 
     @Override
-    public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
-            String instanceName) {
+    public boolean bindService(Intent service, int flags, Executor executor,
+            ServiceConnection conn) {
+        return false;
+    }
+
+    @Override
+    public boolean bindIsolatedService(Intent service, int flags, String instanceName,
+            Executor executor, ServiceConnection conn) {
         return false;
     }
 
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index a12b0a0..fdba723 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -68,6 +68,7 @@
 import android.net.INetd;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
 import android.net.InterfaceConfiguration;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
@@ -123,6 +124,7 @@
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Vector;
 
 @RunWith(AndroidJUnit4.class)
@@ -918,6 +920,67 @@
                 expectedInteractionsWithShowNotification);
     }
 
+    private class TestTetheringEventCallback extends ITetheringEventCallback.Stub {
+        private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
+
+        public void expectUpstreamChanged(Network... networks) {
+            final ArrayList<Network> expectedUpstreams =
+                    new ArrayList<Network>(Arrays.asList(networks));
+            for (Network upstream : expectedUpstreams) {
+                // throws OOB if no expectations
+                assertEquals(mActualUpstreams.remove(0), upstream);
+            }
+            assertNoCallback();
+        }
+
+        @Override
+        public void onUpstreamChanged(Network network) {
+            mActualUpstreams.add(network);
+        }
+
+        public void assertNoCallback() {
+            assertTrue(mActualUpstreams.isEmpty());
+        }
+    }
+
+    @Test
+    public void testRegisterTetheringEventCallback() throws Exception {
+        TestTetheringEventCallback callback1 = new TestTetheringEventCallback();
+        TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
+
+        // 1. Register one callback and run usb tethering.
+        mTethering.registerTetheringEventCallback(callback1);
+        mLooper.dispatchAll();
+        callback1.expectUpstreamChanged(new Network[] {null});
+        NetworkState upstreamState = buildMobileDualStackUpstreamState();
+        runUsbTethering(upstreamState);
+        callback1.expectUpstreamChanged(upstreamState.network);
+        // 2. Register second callback.
+        mTethering.registerTetheringEventCallback(callback2);
+        mLooper.dispatchAll();
+        callback2.expectUpstreamChanged(upstreamState.network);
+        // 3. Disable usb tethering.
+        mTethering.stopTethering(TETHERING_USB);
+        mLooper.dispatchAll();
+        sendUsbBroadcast(false, false, false);
+        mLooper.dispatchAll();
+        callback1.expectUpstreamChanged(new Network[] {null});
+        callback2.expectUpstreamChanged(new Network[] {null});
+        // 4. Unregister first callback and run hotspot.
+        mTethering.unregisterTetheringEventCallback(callback1);
+        mLooper.dispatchAll();
+        when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
+        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
+                .thenReturn(upstreamState);
+        when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
+        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mLooper.dispatchAll();
+        mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
+        sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
+        mLooper.dispatchAll();
+        callback1.assertNoCallback();
+        callback2.expectUpstreamChanged(upstreamState.network);
+    }
 
     // TODO: Test that a request for hotspot mode doesn't interfere with an
     // already operating tethering mode interface.
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6dd838c..4fd00f7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -3604,7 +3604,7 @@
             android.Manifest.permission.NETWORK_SETUP_WIZARD,
             android.Manifest.permission.NETWORK_STACK
     })
-    public void connect(WifiConfiguration config, ActionListener listener) {
+    public void connect(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         // Use INVALID_NETWORK_ID for arg1 when passing a config object
         // arg1 is used to pass network id when the network already exists
@@ -3630,7 +3630,7 @@
             android.Manifest.permission.NETWORK_SETUP_WIZARD,
             android.Manifest.permission.NETWORK_STACK
     })
-    public void connect(int networkId, ActionListener listener) {
+    public void connect(int networkId, @Nullable ActionListener listener) {
         if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
     }
@@ -3661,7 +3661,7 @@
             android.Manifest.permission.NETWORK_SETUP_WIZARD,
             android.Manifest.permission.NETWORK_STACK
     })
-    public void save(WifiConfiguration config, ActionListener listener) {
+    public void save(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
     }
@@ -3685,7 +3685,7 @@
             android.Manifest.permission.NETWORK_SETUP_WIZARD,
             android.Manifest.permission.NETWORK_STACK
     })
-    public void forget(int netId, ActionListener listener) {
+    public void forget(int netId, @Nullable ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener));
     }
@@ -3705,7 +3705,7 @@
             android.Manifest.permission.NETWORK_SETUP_WIZARD,
             android.Manifest.permission.NETWORK_STACK
     })
-    public void disable(int netId, ActionListener listener) {
+    public void disable(int netId, @Nullable ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener));
     }
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index 358bf31..8b56b3f 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -408,7 +408,7 @@
          * @return Instance of {@link NetworkSpecifier}.
          * @throws IllegalStateException on invalid params set.
          */
-        public @NonNull NetworkSpecifier build() {
+        public @NonNull WifiNetworkSpecifier build() {
             if (!hasSetAnyPattern()) {
                 throw new IllegalStateException("one of setSsidPattern/setSsid/setBssidPattern/"
                         + "setBssid should be invoked for specifier");