Merge changes from topic "presubmit-am-c548fd9918a542cebc9e4b0f87a44f0b" into sc-v2-dev-plus-aosp

* changes:
  [automerge] Fixing not responsive tiles in split shade 2p: ab0a84d7a8
  Fixing not responsive tiles in split shade
diff --git a/Android.bp b/Android.bp
index c9391cb..cdfc33e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -97,7 +97,7 @@
         ":platform-compat-native-aidl",
 
         // AIDL sources from external directories
-        ":android.hardware.security.keymint-V1-java-source",
+        ":android.hardware.security.keymint-V2-java-source",
         ":android.hardware.security.secureclock-V1-java-source",
         ":android.security.apc-java-source",
         ":android.security.authorization-java-source",
diff --git a/Android.mk b/Android.mk
index 46529eb..d9e202c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,6 +15,14 @@
 #
 LOCAL_PATH := $(call my-dir)
 
+$(eval $(call declare-1p-copy-files,frameworks/base,.ogg))
+$(eval $(call declare-1p-copy-files,frameworks/base,.kl))
+$(eval $(call declare-1p-copy-files,frameworks/base,.kcm))
+$(eval $(call declare-1p-copy-files,frameworks/base,.idc))
+$(eval $(call declare-1p-copy-files,frameworks/base,dirty-image-objects))
+$(eval $(call declare-1p-copy-files,frameworks/base/config,))
+$(eval $(call declare-1p-copy-files,frameworks/native/data,))
+
 # Load framework-specific path mappings used later in the build.
 include $(LOCAL_PATH)/pathmap.mk
 
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
index 1a710a9..96e88dd 100644
--- a/apex/media/Android.bp
+++ b/apex/media/Android.bp
@@ -18,11 +18,7 @@
         "//frameworks/av/apex/testing",
     ],
     // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
+    default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
 sdk {
diff --git a/apex/media/aidl/Android.bp b/apex/media/aidl/Android.bp
index 545a0cd..4ba0d9b 100644
--- a/apex/media/aidl/Android.bp
+++ b/apex/media/aidl/Android.bp
@@ -16,11 +16,7 @@
 
 package {
     // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
+    default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
 filegroup {
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index 6195f257e..a5e6df1 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -14,11 +14,7 @@
 
 package {
     // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
+    default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
 java_library {
@@ -65,6 +61,7 @@
         "//frameworks/av/apex:__subpackages__",
         "//frameworks/base/apex/media/service",
         "//frameworks/base/api", // For framework-all
+        "//packages/modules/Media/apex/service",
     ],
 }
 
diff --git a/apex/media/service/Android.bp b/apex/media/service/Android.bp
index 271fc53..1911735 100644
--- a/apex/media/service/Android.bp
+++ b/apex/media/service/Android.bp
@@ -13,11 +13,7 @@
 // limitations under the License.
 package {
     // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
+    default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
 filegroup {
diff --git a/core/api/current.txt b/core/api/current.txt
index f7e5273..17551f5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -40057,6 +40057,7 @@
     field public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL = "ims.rcs_bulk_capability_exchange_bool";
     field public static final String KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY = "ims.rcs_feature_tag_allowed_string_array";
     field public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE = "ims.rcs_requires_provisioning_bundle";
+    field public static final String KEY_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL = "ims.use_sip_uri_for_presence_subscribe_bool";
     field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
   }
 
@@ -41133,16 +41134,16 @@
     ctor @Deprecated public ServiceState(android.os.Parcel);
     method protected void copyFrom(android.telephony.ServiceState);
     method public int describeContents();
-    method public int getCdmaNetworkId();
-    method public int getCdmaSystemId();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public int getCdmaNetworkId();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public int getCdmaSystemId();
     method public int[] getCellBandwidths();
     method public int getChannelNumber();
     method public int getDuplexMode();
     method public boolean getIsManualSelection();
     method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
-    method public String getOperatorAlphaLong();
-    method public String getOperatorAlphaShort();
-    method public String getOperatorNumeric();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getOperatorAlphaLong();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getOperatorAlphaShort();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getOperatorNumeric();
     method public boolean getRoaming();
     method public int getState();
     method public boolean isSearching();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index c50b9e9..b6057e2 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -13289,6 +13289,7 @@
     method @Nullable public android.telephony.ims.RcsContactPresenceTuple getCapabilityTuple(@NonNull String);
     method @NonNull public java.util.List<android.telephony.ims.RcsContactPresenceTuple> getCapabilityTuples();
     method @NonNull public android.net.Uri getContactUri();
+    method @Nullable public android.net.Uri getEntityUri();
     method @NonNull public java.util.Set<java.lang.String> getFeatureTags();
     method public int getRequestResult();
     method public int getSourceType();
@@ -13317,6 +13318,7 @@
     method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder addCapabilityTuple(@NonNull android.telephony.ims.RcsContactPresenceTuple);
     method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder addCapabilityTuples(@NonNull java.util.List<android.telephony.ims.RcsContactPresenceTuple>);
     method @NonNull public android.telephony.ims.RcsContactUceCapability build();
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder setEntityUri(@NonNull android.net.Uri);
   }
 
   public class RcsUceAdapter {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 550d1d8..3e236b5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3103,11 +3103,18 @@
         }
     }
 
-    /** @hide */
-    public void resetNewUserDisclaimer() {
+    /**
+     * Acknoledges that the new managed user disclaimer was viewed by the (human) user
+     * so that {@link #ACTION_SHOW_NEW_USER_DISCLAIMER broadcast} is not sent again the next time
+     * this user is switched to.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    public void acknowledgeNewUserDisclaimer() {
         if (mService != null) {
             try {
-                mService.resetNewUserDisclaimer();
+                mService.acknowledgeNewUserDisclaimer();
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -5673,7 +5680,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_SHOW_NEW_USER_DISCLAIMER =
-            "android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER";
+            "android.app.action.SHOW_NEW_USER_DISCLAIMER";
 
     /**
      * Widgets are enabled in keyguard
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7ad8379..4f6ed5c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -265,7 +265,7 @@
     int getLogoutUserId();
     void clearLogoutUser();
     List<UserHandle> getSecondaryUsers(in ComponentName who);
-    void resetNewUserDisclaimer();
+    void acknowledgeNewUserDisclaimer();
 
     void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName);
     int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent);
diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS
index 46b5ea0..e857c72 100644
--- a/core/java/android/app/assist/OWNERS
+++ b/core/java/android/app/assist/OWNERS
@@ -1,7 +1,5 @@
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
 augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/app/contentsuggestions/OWNERS b/core/java/android/app/contentsuggestions/OWNERS
index 482abb2..cf54c2a 100644
--- a/core/java/android/app/contentsuggestions/OWNERS
+++ b/core/java/android/app/contentsuggestions/OWNERS
@@ -1,9 +1,7 @@
 # Bug component: 643919
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
 augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c9d1f54..2df5eec 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3438,7 +3438,7 @@
     public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
 
     /**
-     * Connect to an application service, creating it if needed.  This defines
+     * Connects to an application service, creating it if needed.  This defines
      * a dependency between your application and the service.  The given
      * <var>conn</var> will receive the service object when it is created and be
      * told if it dies and restarts.  The service will be considered required
@@ -3453,11 +3453,8 @@
      * will be invoked instead of
      * {@link ServiceConnection#onServiceConnected(ComponentName, IBinder) onServiceConnected()}.
      *
-     * <p>This method will throw {@link SecurityException} if the calling app does not
-     * have permission to bind to the given service.
-     *
-     * <p class="note">Note: this method <em>cannot be called from a
-     * {@link BroadcastReceiver} component</em>.  A pattern you can use to
+     * <p class="note"><b>Note:</b> This method <em>cannot</em> be called from a
+     * {@link BroadcastReceiver} component.  A pattern you can use to
      * communicate from a BroadcastReceiver to a Service is to call
      * {@link #startService} with the arguments containing the command to be
      * sent, with the service calling its
@@ -3472,34 +3469,34 @@
      *      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.  May be 0,
-     *          {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
-     *          {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
-     *          {@link #BIND_ALLOW_OOM_MANAGEMENT}, {@link #BIND_WAIVE_PRIORITY}.
-     *          {@link #BIND_IMPORTANT}, {@link #BIND_ADJUST_WITH_ACTIVITY},
-     *          {@link #BIND_NOT_PERCEPTIBLE}, or {@link #BIND_INCLUDE_CAPABILITIES}.
-     * @return {@code true} if the system is in the process of bringing up a
+     * @param flags Operation options for the binding. Can be:
+     *      <ul>
+     *          <li>0
+     *          <li>{@link #BIND_AUTO_CREATE}
+     *          <li>{@link #BIND_DEBUG_UNBIND}
+     *          <li>{@link #BIND_NOT_FOREGROUND}
+     *          <li>{@link #BIND_ABOVE_CLIENT}
+     *          <li>{@link #BIND_ALLOW_OOM_MANAGEMENT}
+     *          <li>{@link #BIND_WAIVE_PRIORITY}
+     *          <li>{@link #BIND_IMPORTANT}
+     *          <li>{@link #BIND_ADJUST_WITH_ACTIVITY}
+     *          <li>{@link #BIND_NOT_PERCEPTIBLE}
+     *          <li>{@link #BIND_INCLUDE_CAPABILITIES}
+     *      </ul>
+     *
+      * @return {@code true} if the system is in the process of bringing up a
      *         service that your client has permission to bind to; {@code false}
      *         if the system couldn't find the service or if your client doesn't
-     *         have permission to bind to it. If this value is {@code true}, you
-     *         should later call {@link #unbindService} to release the
-     *         connection.
+     *         have permission to bind to it. You should call {@link #unbindService}
+     *         to release the connection even if this method returned {@code false}.
      *
-     * @throws SecurityException If the caller does not have permission to access the service
-     * or the service can not be found.
+     * @throws SecurityException If the caller does not have permission to
+     *      access the service or the service cannot be found. Call
+     *      {@link #unbindService} to release the connection when this exception
+     *      is thrown.
      *
      * @see #unbindService
      * @see #startService
-     * @see #BIND_AUTO_CREATE
-     * @see #BIND_DEBUG_UNBIND
-     * @see #BIND_NOT_FOREGROUND
-     * @see #BIND_ABOVE_CLIENT
-     * @see #BIND_ALLOW_OOM_MANAGEMENT
-     * @see #BIND_WAIVE_PRIORITY
-     * @see #BIND_IMPORTANT
-     * @see #BIND_ADJUST_WITH_ACTIVITY
-     * @see #BIND_NOT_PERCEPTIBLE
-     * @see #BIND_INCLUDE_CAPABILITIES
      */
     public abstract boolean bindService(@RequiresPermission Intent service,
             @NonNull ServiceConnection conn, @BindServiceFlags int flags);
diff --git a/core/java/android/content/ServiceConnection.java b/core/java/android/content/ServiceConnection.java
index 21398f6..660a7f0 100644
--- a/core/java/android/content/ServiceConnection.java
+++ b/core/java/android/content/ServiceConnection.java
@@ -63,8 +63,12 @@
      * happen, for example, if the application hosting the service it is bound to
      * has been updated.
      *
-     * @param name The concrete component name of the service whose
-     * connection is dead.
+     * <p class="note"><b>Note:</b> The app that requested the binding must call
+     * {@link Context#unbindService(ServiceConnection)} to release the tracking
+     * resources associated with this ServiceConnection even if this callback was
+     * invoked following {@link Context#bindService Context.bindService() bindService()}.
+     *
+     * @param name The concrete component name of the service whose connection is dead.
      */
     default void onBindingDied(ComponentName name) {
     }
@@ -72,10 +76,10 @@
     /**
      * Called when the service being bound has returned {@code null} from its
      * {@link android.app.Service#onBind(Intent) onBind()} method.  This indicates
-     * that the attempting service binding represented by this ServiceConnection
+     * that the attempted service binding represented by this ServiceConnection
      * will never become usable.
      *
-     * <p class="note">The app which requested the binding must still call
+     * <p class="note"><b>Note:</b> The app that requested the binding must still call
      * {@link Context#unbindService(ServiceConnection)} to release the tracking
      * resources associated with this ServiceConnection even if this callback was
      * invoked following {@link Context#bindService Context.bindService() bindService()}.
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index e3ff089..ee62170 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -638,7 +638,7 @@
     /**
      * Unregisters a listener for the sensors with which it is registered.
      *
-     * <p class="note"></p>
+     * <p class="note">
      * Note: Don't use this method with a one shot trigger sensor such as
      * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
      * Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead.
diff --git a/core/java/android/service/autofill/OWNERS b/core/java/android/service/autofill/OWNERS
index a088632..9a30e82 100644
--- a/core/java/android/service/autofill/OWNERS
+++ b/core/java/android/service/autofill/OWNERS
@@ -1,9 +1,3 @@
 # Bug component: 351486
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/java/android/service/contentcapture/OWNERS b/core/java/android/service/contentcapture/OWNERS
index 6337327..24561c5 100644
--- a/core/java/android/service/contentcapture/OWNERS
+++ b/core/java/android/service/contentcapture/OWNERS
@@ -1,9 +1,3 @@
 # Bug component: 544200
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+include /core/java/android/view/contentcapture/OWNERS
diff --git a/core/java/android/service/contentsuggestions/OWNERS b/core/java/android/service/contentsuggestions/OWNERS
index 46b5ea0..72fe0b1 100644
--- a/core/java/android/service/contentsuggestions/OWNERS
+++ b/core/java/android/service/contentsuggestions/OWNERS
@@ -1,7 +1,2 @@
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+
+include /core/java/android/app/contentsuggestions/OWNERS
diff --git a/core/java/android/service/resumeonreboot/OWNERS b/core/java/android/service/resumeonreboot/OWNERS
index 3a127d5..721fbaf 100644
--- a/core/java/android/service/resumeonreboot/OWNERS
+++ b/core/java/android/service/resumeonreboot/OWNERS
@@ -1,2 +1 @@
-xunchang@google.com
-zhaojiac@google.com
+ejyzhang@google.com
\ No newline at end of file
diff --git a/core/java/android/service/textclassifier/OWNERS b/core/java/android/service/textclassifier/OWNERS
index a535f52..c85c69e 100644
--- a/core/java/android/service/textclassifier/OWNERS
+++ b/core/java/android/service/textclassifier/OWNERS
@@ -1,9 +1,3 @@
 # Bug component: 709498
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+include /core/java/android/view/textclassifier/OWNERS
diff --git a/core/java/android/service/translation/OWNERS b/core/java/android/service/translation/OWNERS
index a1e663a..440f9a8 100644
--- a/core/java/android/service/translation/OWNERS
+++ b/core/java/android/service/translation/OWNERS
@@ -1,8 +1,3 @@
 # Bug component: 994311
 
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+include /core/java/android/view/translation/OWNERS
diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS
index 46b5ea0..59a0c2e 100644
--- a/core/java/android/service/voice/OWNERS
+++ b/core/java/android/service/voice/OWNERS
@@ -1,7 +1,3 @@
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+# Bug component: 533220
+
+include /core/java/android/app/assist/OWNERS
diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS
index a088632..108c42c 100644
--- a/core/java/android/view/autofill/OWNERS
+++ b/core/java/android/view/autofill/OWNERS
@@ -1,9 +1,7 @@
 # Bug component: 351486
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
 augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
index 6337327..1a5cb1e4 100644
--- a/core/java/android/view/contentcapture/OWNERS
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -1,9 +1,7 @@
 # Bug component: 544200
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
 augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/view/inputmethod/OWNERS b/core/java/android/view/inputmethod/OWNERS
index d7db7c7..9fa7e8f 100644
--- a/core/java/android/view/inputmethod/OWNERS
+++ b/core/java/android/view/inputmethod/OWNERS
@@ -3,4 +3,4 @@
 
 include /services/core/java/com/android/server/inputmethod/OWNERS
 
-per-file *InlineSuggestion* = file:/core/java/android/service/autofill/OWNERS
+per-file *InlineSuggestion* = file:/core/java/android/view/autofill/OWNERS
diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS
index 4bcdeea..a205be2 100644
--- a/core/java/android/view/textclassifier/OWNERS
+++ b/core/java/android/view/textclassifier/OWNERS
@@ -2,8 +2,6 @@
 
 mns@google.com
 toki@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
 augale@google.com
 joannechung@google.com
 tonymak@google.com
diff --git a/core/java/android/view/textclassifier/logging/OWNERS b/core/java/android/view/textclassifier/logging/OWNERS
deleted file mode 100644
index ac80d9f..0000000
--- a/core/java/android/view/textclassifier/logging/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-# Bug component: 709498
-
-mns@google.com
-toki@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
-augale@google.com
-joannechung@google.com
diff --git a/core/java/android/view/translation/OWNERS b/core/java/android/view/translation/OWNERS
index a1e663a..b772ad3 100644
--- a/core/java/android/view/translation/OWNERS
+++ b/core/java/android/view/translation/OWNERS
@@ -1,8 +1,7 @@
 # Bug component: 994311
 
-adamhe@google.com
 augale@google.com
 joannechung@google.com
+markpun@google.com
 lpeter@google.com
-svetoslavganov@google.com
 tymtsai@google.com
diff --git a/core/java/android/widget/inline/OWNERS b/core/java/android/widget/inline/OWNERS
new file mode 100644
index 0000000..9a30e82
--- /dev/null
+++ b/core/java/android/widget/inline/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 351486
+
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2e17779..c037e7c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -711,7 +711,7 @@
     <protected-broadcast android:name="android.scheduling.action.REBOOT_READY" />
     <protected-broadcast android:name="android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED" />
     <protected-broadcast android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" />
-    <protected-broadcast android:name="android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER" />
+    <protected-broadcast android:name="android.app.action.SHOW_NEW_USER_DISCLAIMER" />
 
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
diff --git a/core/tests/coretests/src/android/widget/OWNERS b/core/tests/coretests/src/android/widget/OWNERS
new file mode 100644
index 0000000..5a9aed3
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/OWNERS
@@ -0,0 +1,5 @@
+include /core/java/android/widget/OWNERS
+
+per-file *SuggestionsPopup* = file:/core/java/android/text/OWNERS
+
+per-file *FloatingToolbar*, *SelectionToolbar* = file:/core/java/android/view/textclassifier/OWNERS
\ No newline at end of file
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index be1e2b2..dc07758 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C} 2018 The Android Open Source Project
+// Copyright (C) 2018 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License"};
 // you may not use this file except in compliance with the License.
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-
 // Sysconfig files
 
 package {
@@ -134,13 +133,6 @@
 }
 
 prebuilt_etc {
-    name: "privapp_whitelist_com.android.networkstack.tethering",
-    sub_dir: "permissions",
-    src: "com.android.networkstack.tethering.xml",
-    filename_from_src: true,
-}
-
-prebuilt_etc {
     name: "privapp_whitelist_com.android.provision",
     system_ext_specific: true,
     sub_dir: "permissions",
diff --git a/data/etc/com.android.networkstack.tethering.xml b/data/etc/com.android.networkstack.tethering.xml
deleted file mode 100644
index f26a961..0000000
--- a/data/etc/com.android.networkstack.tethering.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2021 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
--->
-
-<permissions>
-    <privapp-permissions package="com.android.networkstack.tethering">
-        <permission name="android.permission.BLUETOOTH_PRIVILEGED" />
-        <permission name="android.permission.MANAGE_USB"/>
-        <permission name="android.permission.MODIFY_PHONE_STATE"/>
-        <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
-        <permission name="android.permission.TETHER_PRIVILEGED"/>
-        <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
-        <permission name="android.permission.UPDATE_DEVICE_STATS"/>
-      </privapp-permissions>
-</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 0d01253..191d400 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -464,6 +464,9 @@
         <permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
         <permission name="android.permission.NEARBY_WIFI_DEVICES" />
         <permission name="android.permission.OVERRIDE_WIFI_CONFIG" />
+        <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
+             P2P external approver API sets require MANAGE_WIFI_AUTO_JOIN permission. -->
+        <permission name="android.permission.MANAGE_WIFI_AUTO_JOIN" />
         <!-- Permission required for CTS test CarrierMessagingServiceWrapperTest -->
         <permission name="android.permission.BIND_CARRIER_SERVICES"/>
         <!-- Permission required for CTS test - MusicRecognitionManagerTest -->
diff --git a/libs/androidfw/tests/BackupHelpers_test.cpp b/libs/androidfw/tests/BackupHelpers_test.cpp
index 86b7fb3..c2fcb69 100644
--- a/libs/androidfw/tests/BackupHelpers_test.cpp
+++ b/libs/androidfw/tests/BackupHelpers_test.cpp
@@ -50,7 +50,7 @@
 TEST_F(BackupHelpersTest, WriteTarFileWithSizeGreaterThan2GB) {
   TemporaryFile tf;
   // Allocate a 2 GB file.
-  off64_t fileSize = 2ll * 1024ll * 1024ll * 1024ll + 512ll;
+  off64_t fileSize = 2LL * 1024LL * 1024LL * 1024LL + 512LL;
   ASSERT_EQ(0, posix_fallocate64(tf.fd, 0, fileSize));
   off64_t tarSize = 0;
   int err = write_tarfile(/* packageName */ String8("test-pkg"), /* domain */ String8(""), /* rootpath */ String8(""), /* filePath */ String8(tf.path), /* outSize */ &tarSize, /* writer */ NULL);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
index 1a955c4..72243f9 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
@@ -146,7 +146,7 @@
          * @param iface the name of the interface.
          * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
          *              interface was removed.
-         * @param role whether the interface is in the client mode or server mode.
+         * @param role whether the interface is in client mode or server mode.
          * @param configuration the current IP configuration of the interface.
          * @hide
          */
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
index 9f3371b..eeb56d0 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
@@ -51,6 +51,7 @@
 import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG;
 import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT;
 import static android.os.Trace.TRACE_TAG_NETWORK;
+import static android.system.OsConstants.ENOENT;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
@@ -120,7 +121,6 @@
 import android.service.NetworkInterfaceProto;
 import android.service.NetworkStatsServiceDumpProto;
 import android.system.ErrnoException;
-import android.system.Os;
 import android.telephony.PhoneStateListener;
 import android.telephony.SubscriptionPlan;
 import android.text.TextUtils;
@@ -214,6 +214,14 @@
     // This is current path but may be changed soon.
     private static final String UID_COUNTERSET_MAP_PATH =
             "/sys/fs/bpf/map_netd_uid_counterset_map";
+    private static final String COOKIE_TAG_MAP_PATH =
+            "/sys/fs/bpf/map_netd_cookie_tag_map";
+    private static final String APP_UID_STATS_MAP_PATH =
+            "/sys/fs/bpf/map_netd_app_uid_stats_map";
+    private static final String STATS_MAP_A_PATH =
+            "/sys/fs/bpf/map_netd_stats_map_A";
+    private static final String STATS_MAP_B_PATH =
+            "/sys/fs/bpf/map_netd_stats_map_B";
 
     private final Context mContext;
     private final NetworkStatsFactory mStatsFactory;
@@ -341,6 +349,10 @@
      */
     private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
     private final IBpfMap<U32, U8> mUidCounterSetMap;
+    private final IBpfMap<CookieTagMapKey, CookieTagMapValue> mCookieTagMap;
+    private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapA;
+    private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapB;
+    private final IBpfMap<UidStatsMapKey, StatsMapValue> mAppUidStatsMap;
 
     /** Data layer operation counters for splicing into other structures. */
     private NetworkStats mUidOperations = new NetworkStats(0L, 10);
@@ -474,6 +486,10 @@
         mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler);
         mInterfaceMapUpdater.start();
         mUidCounterSetMap = mDeps.getUidCounterSetMap();
+        mCookieTagMap = mDeps.getCookieTagMap();
+        mStatsMapA = mDeps.getStatsMapA();
+        mStatsMapB = mDeps.getStatsMapB();
+        mAppUidStatsMap = mDeps.getAppUidStatsMap();
     }
 
     /**
@@ -547,8 +563,48 @@
             }
         }
 
-        public TagStatsDeleter getTagStatsDeleter() {
-            return NetworkStatsService::nativeDeleteTagData;
+        /** Gets the cookie tag map */
+        public IBpfMap<CookieTagMapKey, CookieTagMapValue> getCookieTagMap() {
+            try {
+                return new BpfMap<CookieTagMapKey, CookieTagMapValue>(COOKIE_TAG_MAP_PATH,
+                        BpfMap.BPF_F_RDWR, CookieTagMapKey.class, CookieTagMapValue.class);
+            } catch (ErrnoException e) {
+                Log.wtf(TAG, "Cannot create cookie tag map: " + e);
+                return null;
+            }
+        }
+
+        /** Gets stats map A */
+        public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapA() {
+            try {
+                return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_A_PATH,
+                        BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
+            } catch (ErrnoException e) {
+                Log.wtf(TAG, "Cannot create stats map A: " + e);
+                return null;
+            }
+        }
+
+        /** Gets stats map B */
+        public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapB() {
+            try {
+                return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_B_PATH,
+                        BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
+            } catch (ErrnoException e) {
+                Log.wtf(TAG, "Cannot create stats map B: " + e);
+                return null;
+            }
+        }
+
+        /** Gets the uid stats map */
+        public IBpfMap<UidStatsMapKey, StatsMapValue> getAppUidStatsMap() {
+            try {
+                return new BpfMap<UidStatsMapKey, StatsMapValue>(APP_UID_STATS_MAP_PATH,
+                        BpfMap.BPF_F_RDWR, UidStatsMapKey.class, StatsMapValue.class);
+            } catch (ErrnoException e) {
+                Log.wtf(TAG, "Cannot create app uid stats map: " + e);
+                return null;
+            }
         }
     }
 
@@ -1790,6 +1846,63 @@
                 currentTime);
     }
 
+    // deleteKernelTagData can ignore ENOENT; otherwise we should log an error
+    private void logErrorIfNotErrNoent(final ErrnoException e, final String msg) {
+        if (e.errno != ENOENT) Log.e(TAG, msg, e);
+    }
+
+    private <K extends StatsMapKey, V extends StatsMapValue> void deleteStatsMapTagData(
+            IBpfMap<K, V> statsMap, int uid) {
+        try {
+            statsMap.forEach((key, value) -> {
+                if (key.uid == uid) {
+                    try {
+                        statsMap.deleteEntry(key);
+                    } catch (ErrnoException e) {
+                        logErrorIfNotErrNoent(e, "Failed to delete data(uid = " + key.uid + ")");
+                    }
+                }
+            });
+        } catch (ErrnoException e) {
+            Log.e(TAG, "FAILED to delete tag data from stats map", e);
+        }
+    }
+
+    /**
+     * Deletes uid tag data from CookieTagMap, StatsMapA, StatsMapB, and UidStatsMap
+     * @param uid
+     */
+    private void deleteKernelTagData(int uid) {
+        try {
+            mCookieTagMap.forEach((key, value) -> {
+                if (value.uid == uid) {
+                    try {
+                        mCookieTagMap.deleteEntry(key);
+                    } catch (ErrnoException e) {
+                        logErrorIfNotErrNoent(e, "Failed to delete data(cookie = " + key + ")");
+                    }
+                }
+            });
+        } catch (ErrnoException e) {
+            Log.e(TAG, "Failed to delete tag data from cookie tag map", e);
+        }
+
+        deleteStatsMapTagData(mStatsMapA, uid);
+        deleteStatsMapTagData(mStatsMapB, uid);
+
+        try {
+            mUidCounterSetMap.deleteEntry(new U32(uid));
+        } catch (ErrnoException e) {
+            logErrorIfNotErrNoent(e, "Failed to delete tag data from uid counter set map");
+        }
+
+        try {
+            mAppUidStatsMap.deleteEntry(new UidStatsMapKey(uid));
+        } catch (ErrnoException e) {
+            logErrorIfNotErrNoent(e, "Failed to delete tag data from app uid stats map");
+        }
+    }
+
     /**
      * Clean up {@link #mUidRecorder} after UID is removed.
      */
@@ -1805,10 +1918,7 @@
 
         // Clear kernel stats associated with UID
         for (int uid : uids) {
-            final int ret = mDeps.getTagStatsDeleter().deleteTagData(uid);
-            if (ret < 0) {
-                Log.w(TAG, "problem clearing counters for uid " + uid + ": " + Os.strerror(-ret));
-            }
+            deleteKernelTagData(uid);
         }
     }
 
@@ -2387,12 +2497,4 @@
     private static native long nativeGetTotalStat(int type);
     private static native long nativeGetIfaceStat(String iface, int type);
     private static native long nativeGetUidStat(int uid, int type);
-
-    // TODO: use BpfNetMaps to delete tag data and remove this.
-    @VisibleForTesting
-    interface TagStatsDeleter {
-        int deleteTagData(int uid);
-    }
-
-    private static native int nativeDeleteTagData(int uid);
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 86604a2..610e3d5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -165,6 +165,31 @@
         return sessionInfos.get(sessionInfos.size() - 1);
     }
 
+    boolean isRoutingSessionAvailableForVolumeControl() {
+        if (mVolumeAdjustmentForRemoteGroupSessions) {
+            return true;
+        }
+        List<RoutingSessionInfo> sessions =
+                mRouterManager.getRoutingSessions(mPackageName);
+        boolean foundNonSystemSession = false;
+        boolean isGroup = false;
+        for (RoutingSessionInfo session : sessions) {
+            if (!session.isSystemSession()) {
+                foundNonSystemSession = true;
+                int selectedRouteCount = session.getSelectedRoutes().size();
+                if (selectedRouteCount > 1) {
+                    isGroup = true;
+                    break;
+                }
+            }
+        }
+        if (!foundNonSystemSession) {
+            Log.d(TAG, "No routing session for " + mPackageName);
+            return false;
+        }
+        return !isGroup;
+    }
+
     /**
      * Remove a {@code device} from current media.
      *
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index b5facf3..c8db654 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -197,6 +197,14 @@
     }
 
     /**
+     * Returns if the media session is available for volume control.
+     * @return True if this media session is available for colume control, false otherwise.
+     */
+    public boolean isMediaSessionAvailableForVolumeControl() {
+        return mInfoMediaManager.isRoutingSessionAvailableForVolumeControl();
+    }
+
+    /**
      * Start scan connected MediaDevice
      */
     public void startScan() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
index d7b366e..bb6b293 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -206,9 +206,8 @@
 
         when(config.isMandatoryCodec()).thenReturn(false);
         when(config.getCodecType()).thenReturn(4);
-        when(config.getCodecName()).thenReturn("LDAC");
         assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(
-                String.format(KNOWN_CODEC_LABEL, config.getCodecName()));
+                String.format(KNOWN_CODEC_LABEL, "LDAC"));
     }
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index d53a3e8..298ee90 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -28,6 +28,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
+import android.os.Parcel;
 import android.os.ParcelUuid;
 
 import org.junit.Before;
@@ -60,9 +61,9 @@
     private final static Map<Integer, ParcelUuid> CAP_GROUP2 =
             Map.of(2, BluetoothUuid.CAP);
     private final BluetoothClass DEVICE_CLASS_1 =
-        new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
     private final BluetoothClass DEVICE_CLASS_2 =
-        new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
     @Mock
     private LocalBluetoothProfileManager mLocalProfileManager;
     @Mock
@@ -92,6 +93,16 @@
     private HearingAidDeviceManager mHearingAidDeviceManager;
     private Context mContext;
 
+    private BluetoothClass createBtClass(int deviceClass) {
+        Parcel p = Parcel.obtain();
+        p.writeInt(deviceClass);
+        p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+        BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+        p.recycle();
+        return bluetoothClass;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
index 7be176a..a8e6075 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
@@ -28,6 +28,7 @@
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
+import android.os.Parcel;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -48,7 +49,7 @@
     private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
     private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
     private final BluetoothClass DEVICE_CLASS =
-            new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
     @Mock
     private LocalBluetoothProfileManager mLocalProfileManager;
     @Mock
@@ -67,6 +68,16 @@
     private HearingAidDeviceManager mHearingAidDeviceManager;
     private Context mContext;
 
+    private BluetoothClass createBtClass(int deviceClass) {
+        Parcel p = Parcel.obtain();
+        p.writeInt(deviceClass);
+        p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+        BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+        p.recycle();
+        return bluetoothClass;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index 6f7f73a..c122a37 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -31,6 +31,7 @@
 import android.content.Context;
 import android.media.MediaRoute2Info;
 import android.media.MediaRouter2Manager;
+import android.os.Parcel;
 
 import com.android.settingslib.bluetooth.A2dpProfile;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -65,9 +66,9 @@
     private static final String ROUTER_ID_3 = "RouterId_3";
     private static final String TEST_PACKAGE_NAME = "com.test.playmusic";
     private final BluetoothClass mHeadreeClass =
-            new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
     private final BluetoothClass mCarkitClass =
-            new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO);
 
     @Mock
     private BluetoothDevice mDevice1;
@@ -118,6 +119,16 @@
     private List<MediaDevice> mMediaDevices = new ArrayList<>();
     private PhoneMediaDevice mPhoneMediaDevice;
 
+    private BluetoothClass createBtClass(int deviceClass) {
+        Parcel p = Parcel.obtain();
+        p.writeInt(deviceClass);
+        p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+        BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+        p.recycle();
+        return bluetoothClass;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
diff --git a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
index 3b7fbc7..c7e96bc 100644
--- a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
+++ b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
@@ -69,7 +69,7 @@
     }
 
     @Implementation
-    protected boolean removeActiveDevice(@BluetoothAdapter.ActiveDeviceUse int profiles) {
+    protected boolean removeActiveDevice(int profiles) {
         if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
                 && profiles != ACTIVE_DEVICE_ALL) {
             return false;
@@ -78,8 +78,7 @@
     }
 
     @Implementation
-    protected boolean setActiveDevice(BluetoothDevice device,
-            @BluetoothAdapter.ActiveDeviceUse int profiles) {
+    protected boolean setActiveDevice(BluetoothDevice device, int profiles) {
         if (device == null) {
             return false;
         }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 074d85c..8b27522 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -509,6 +509,9 @@
     <uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
     <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
     <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
+    <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
+         P2P external approver API sets require MANAGE_WIFI_AUTO_JOIN permission. -->
+    <uses-permission android:name="android.permission.MANAGE_WIFI_AUTO_JOIN" />
 
     <!-- Permission required for CTS tests to enable/disable rate limiting toasts. -->
     <uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" />
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index befb648..789ad62 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -118,9 +118,11 @@
             switch (this) {
                 case UNINITIALIZED:
                 case INITIALIZED:
-                case DOZE_REQUEST_PULSE:
                     return parameters.shouldControlScreenOff() ? Display.STATE_ON
                             : Display.STATE_OFF;
+                case DOZE_REQUEST_PULSE:
+                    return parameters.getDisplayNeedsBlanking() ? Display.STATE_OFF
+                            : Display.STATE_ON;
                 case DOZE_AOD_PAUSED:
                 case DOZE:
                     return Display.STATE_OFF;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 3631938..52db1bd 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -105,17 +105,7 @@
 
         updateUdfpsController();
         if (mUdfpsController == null) {
-            mAuthController.addCallback(new AuthController.Callback() {
-                @Override
-                public void onAllAuthenticatorsRegistered() {
-                    updateUdfpsController();
-                }
-
-                @Override
-                public void onEnrollmentsChanged() {
-                    updateUdfpsController();
-                }
-            });
+            mAuthController.addCallback(mAuthControllerCallback);
         }
     }
 
@@ -128,6 +118,11 @@
     }
 
     @Override
+    public void destroy() {
+        mAuthController.removeCallback(mAuthControllerCallback);
+    }
+
+    @Override
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
         int screenState = newState.screenState(mParameters);
         mDozeHost.cancelGentleSleep();
@@ -222,4 +217,16 @@
             mWakeLock.setAcquired(false);
         }
     }
+
+    private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
+        @Override
+        public void onAllAuthenticatorsRegistered() {
+            updateUdfpsController();
+        }
+
+        @Override
+        public void onEnrollmentsChanged() {
+            updateUdfpsController();
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index c8cd432..a7640ff 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -28,6 +28,7 @@
 import android.view.ViewGroup
 import android.view.ViewGroupOverlay
 import androidx.annotation.VisibleForTesting
+import com.android.keyguard.KeyguardViewController
 import com.android.systemui.R
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dagger.SysUISingleton
@@ -39,7 +40,6 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator
 import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.Utils
@@ -82,7 +82,7 @@
     private val notifLockscreenUserManager: NotificationLockscreenUserManager,
     configurationController: ConfigurationController,
     wakefulnessLifecycle: WakefulnessLifecycle,
-    private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+    private val keyguardViewController: KeyguardViewController
 ) {
 
     /**
@@ -998,7 +998,7 @@
 
     private fun isLockScreenVisibleToUser(): Boolean {
         return !statusBarStateController.isDozing &&
-                !statusBarKeyguardViewManager.isBouncerShowing &&
+                !keyguardViewController.isBouncerShowing &&
                 statusBarStateController.state == StatusBarState.KEYGUARD &&
                 notifLockscreenUserManager.shouldShowLockscreenNotifications() &&
                 statusBarStateController.isExpanded &&
@@ -1007,7 +1007,7 @@
 
     private fun isLockScreenShadeVisibleToUser(): Boolean {
         return !statusBarStateController.isDozing &&
-                !statusBarKeyguardViewManager.isBouncerShowing &&
+                !keyguardViewController.isBouncerShowing &&
                 (statusBarStateController.state == StatusBarState.SHADE_LOCKED ||
                         (statusBarStateController.state == StatusBarState.KEYGUARD && qsExpanded))
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index a82e989..e01916f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -111,7 +111,8 @@
             }
             mBottomDivider.setVisibility(View.GONE);
             mCheckBox.setVisibility(View.GONE);
-            if (currentlyConnected && mController.isActiveRemoteDevice(device)) {
+            if (currentlyConnected && mController.isActiveRemoteDevice(device)
+                    && mController.getSelectableMediaDevice().size() > 0) {
                 // Init active device layout
                 mAddIcon.setVisibility(View.VISIBLE);
                 mAddIcon.setTransitionAlpha(1);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 9eaedd7..0d368fa 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -84,7 +84,6 @@
     private final SystemUIDialogManager mDialogManager;
     private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
     private final boolean mAboveStatusbar;
-    private final boolean mVolumeAdjustmentForRemoteGroupSessions;
     private final NotificationEntryManager mNotificationEntryManager;
     @VisibleForTesting
     final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
@@ -117,8 +116,6 @@
         mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
         mUiEventLogger = uiEventLogger;
         mDialogLaunchAnimator = dialogLaunchAnimator;
-        mVolumeAdjustmentForRemoteGroupSessions = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions);
         mDialogManager = dialogManager;
     }
 
@@ -496,10 +493,15 @@
                 || features.contains(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK));
     }
 
+    private boolean isPlayBackInfoLocal() {
+        return mMediaController.getPlaybackInfo() != null
+                && mMediaController.getPlaybackInfo().getPlaybackType()
+                        == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL;
+    }
+
     boolean isVolumeControlEnabled(@NonNull MediaDevice device) {
-        // TODO(b/202500642): Also enable volume control for remote non-group sessions.
-        return !isActiveRemoteDevice(device)
-            || mVolumeAdjustmentForRemoteGroupSessions;
+        return isPlayBackInfoLocal()
+                || mLocalMediaManager.isMediaSessionAvailableForVolumeControl();
     }
 
     private final MediaController.Callback mCb = new MediaController.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 38cefe6..f1e5b56 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -429,7 +429,6 @@
     public void setBrightnessMirrorController(
             BrightnessMirrorController brightnessMirrorController) {
         mQSPanelController.setBrightnessMirror(brightnessMirrorController);
-        mQuickQSPanelController.setBrightnessMirror(brightnessMirrorController);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
deleted file mode 100644
index 65889d7..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs
-
-import androidx.annotation.VisibleForTesting
-import com.android.systemui.settings.brightness.BrightnessController
-import com.android.systemui.settings.brightness.BrightnessSliderController
-import com.android.systemui.settings.brightness.MirroredBrightnessController
-import com.android.systemui.statusbar.policy.BrightnessMirrorController
-import javax.inject.Inject
-
-/**
- * Controls brightness slider in QQS, which is visible only in split shade. It's responsible for
- * showing/hiding it when appropriate and (un)registering listeners
- */
-class QuickQSBrightnessController @VisibleForTesting constructor(
-    private val brightnessControllerFactory: () -> BrightnessController
-) : MirroredBrightnessController {
-
-    @Inject constructor(
-        brightnessControllerFactory: BrightnessController.Factory,
-        brightnessSliderControllerFactory: BrightnessSliderController.Factory,
-        quickQSPanel: QuickQSPanel
-    ) : this(brightnessControllerFactory = {
-            val slider = brightnessSliderControllerFactory.create(quickQSPanel.context,
-                    quickQSPanel)
-            slider.init()
-            quickQSPanel.setBrightnessView(slider.rootView)
-            brightnessControllerFactory.create(slider)
-        })
-
-    private var isListening = false
-    private var brightnessController: BrightnessController? = null
-    private var mirrorController: BrightnessMirrorController? = null
-
-    fun init(shouldUseSplitNotificationShade: Boolean) {
-        refreshVisibility(shouldUseSplitNotificationShade)
-    }
-
-    /**
-     * Starts/Stops listening for brightness changing events.
-     * It's fine to call this function even if slider is not visible (which would be the case for
-     * all small screen devices), it will just do nothing in that case
-     */
-    fun setListening(listening: Boolean) {
-        if (listening) {
-            // controller can be null when slider was never shown
-            if (!isListening && brightnessController != null) {
-                brightnessController?.registerCallbacks()
-                isListening = true
-            }
-        } else {
-            brightnessController?.unregisterCallbacks()
-            isListening = false
-        }
-    }
-
-    fun checkRestrictionAndSetEnabled() {
-        brightnessController?.checkRestrictionAndSetEnabled()
-    }
-
-    fun refreshVisibility(shouldUseSplitNotificationShade: Boolean) {
-        if (shouldUseSplitNotificationShade) {
-            showBrightnessSlider()
-        } else {
-            hideBrightnessSlider()
-        }
-    }
-
-    override fun setMirror(controller: BrightnessMirrorController) {
-        mirrorController = controller
-        mirrorController?.let { brightnessController?.setMirror(it) }
-    }
-
-    private fun hideBrightnessSlider() {
-        brightnessController?.hideSlider()
-    }
-
-    private fun showBrightnessSlider() {
-        if (brightnessController == null) {
-            brightnessController = brightnessControllerFactory()
-            mirrorController?.also { brightnessController?.setMirror(it) }
-            brightnessController?.registerCallbacks()
-            isListening = true
-        }
-        brightnessController?.showSlider()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 92690c7d..fdd764c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -30,8 +30,6 @@
 import com.android.systemui.qs.customize.QSCustomizerController;
 import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -51,9 +49,6 @@
                 }
             };
 
-    // brightness is visible only in split shade
-    private final QuickQSBrightnessController mBrightnessController;
-    private final BrightnessMirrorHandler mBrightnessMirrorHandler;
     private final FooterActionsController mFooterActionsController;
 
     @Inject
@@ -63,13 +58,10 @@
             @Named(QUICK_QS_PANEL) MediaHost mediaHost,
             MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
             DumpManager dumpManager,
-            QuickQSBrightnessController quickQSBrightnessController,
             @Named(QQS_FOOTER) FooterActionsController footerActionsController
     ) {
         super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
                 uiEventLogger, qsLogger, dumpManager);
-        mBrightnessController = quickQSBrightnessController;
-        mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
         mFooterActionsController = footerActionsController;
     }
 
@@ -79,7 +71,6 @@
         mMediaHost.setExpansion(0.0f);
         mMediaHost.setShowsOnlyActiveMedia(true);
         mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
-        mBrightnessController.init(mShouldUseSplitNotificationShade);
         mFooterActionsController.init();
         mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade);
     }
@@ -88,20 +79,17 @@
     protected void onViewAttached() {
         super.onViewAttached();
         mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
-        mBrightnessMirrorHandler.onQsPanelAttached();
     }
 
     @Override
     protected void onViewDetached() {
         super.onViewDetached();
         mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
-        mBrightnessMirrorHandler.onQsPanelDettached();
     }
 
     @Override
     void setListening(boolean listening) {
         super.setListening(listening);
-        mBrightnessController.setListening(listening);
         mFooterActionsController.setListening(listening);
     }
 
@@ -115,14 +103,7 @@
     }
 
     @Override
-    public void refreshAllTiles() {
-        mBrightnessController.checkRestrictionAndSetEnabled();
-        super.refreshAllTiles();
-    }
-
-    @Override
     protected void onConfigurationChanged() {
-        mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade);
         mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade);
     }
 
@@ -146,8 +127,4 @@
     public int getNumQuickTiles() {
         return mView.getNumQuickTiles();
     }
-
-    public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) {
-        mBrightnessMirrorHandler.setController(brightnessMirrorController);
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 8078b6c..5684429 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -42,12 +42,14 @@
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.testing.AndroidTestingRunner;
 import android.testing.UiThreadTest;
+import android.view.Display;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.util.wakelock.WakeLockFake;
 
@@ -444,4 +446,20 @@
 
         assertTrue(mServiceFake.requestedWakeup);
     }
+
+    @Test
+    public void testDozePulsing_displayRequiresBlanking_screenState() {
+        DozeParameters dozeParameters = mock(DozeParameters.class);
+        when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
+
+        assertEquals(Display.STATE_OFF, DOZE_REQUEST_PULSE.screenState(dozeParameters));
+    }
+
+    @Test
+    public void testDozePulsing_displayDoesNotRequireBlanking_screenState() {
+        DozeParameters dozeParameters = mock(DozeParameters.class);
+        when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(false);
+
+        assertEquals(Display.STATE_ON, DOZE_REQUEST_PULSE.screenState(dozeParameters));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 3e19cc4..992a82b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -35,6 +35,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Matchers.anyObject;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.verify;
@@ -306,4 +307,11 @@
         // THEN the display screen state will change
         assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
     }
+
+    @Test
+    public void authCallbackRemovedOnDestroy() {
+        mScreen.destroy();
+
+        verify(mAuthController).removeCallback(anyObject());
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
index a3ffb2f..7565fe1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
@@ -22,6 +22,7 @@
 import android.view.ViewGroup
 import android.widget.FrameLayout
 import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardViewController
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq
@@ -31,7 +32,6 @@
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.animation.UniqueObjectHostView
@@ -80,7 +80,7 @@
     @Mock
     private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
     @Mock
-    private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+    private lateinit var keyguardViewController: KeyguardViewController
     @Mock
     private lateinit var configurationController: ConfigurationController
     @Mock
@@ -110,7 +110,7 @@
                 notificationLockscreenUserManager,
                 configurationController,
                 wakefulnessLifecycle,
-                statusBarKeyguardViewManager)
+                keyguardViewController)
         verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
         verify(statusBarStateController).addCallback(statusBarCallback.capture())
         setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt
deleted file mode 100644
index de1d86b..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs
-
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.settings.brightness.BrightnessController
-import com.android.systemui.statusbar.policy.BrightnessMirrorController
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.mockito.Mock
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.never
-import org.mockito.Mockito.mock
-import org.mockito.junit.MockitoJUnit
-
-@SmallTest
-class QuickQSBrightnessControllerTest : SysuiTestCase() {
-
-    @Mock
-    lateinit var brightnessController: BrightnessController
-    @get:Rule
-    val mockito = MockitoJUnit.rule()
-
-    lateinit var quickQSBrightnessController: QuickQSBrightnessController
-
-    @Before
-    fun setUp() {
-        quickQSBrightnessController = QuickQSBrightnessController(
-                brightnessControllerFactory = { brightnessController })
-    }
-
-    @Test
-    fun testSliderIsShownWhenInitializedInSplitShade() {
-        quickQSBrightnessController.init(shouldUseSplitNotificationShade = true)
-
-        verify(brightnessController).showSlider()
-    }
-
-    @Test
-    fun testSliderIsShownWhenRefreshedInSplitShade() {
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-
-        verify(brightnessController, times(1)).showSlider()
-    }
-
-    @Test
-    fun testSliderIsHiddenWhenRefreshedInNonSplitShade() {
-        // needs to be shown first
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
-
-        verify(brightnessController).hideSlider()
-    }
-
-    @Test
-    fun testSliderChangesVisibilityWhenRotating() {
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-        verify(brightnessController, times(1)).showSlider()
-
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
-        verify(brightnessController, times(1)).hideSlider()
-    }
-
-    @Test
-    fun testCallbacksAreRegisteredOnlyOnce() {
-        // this flow simulates expanding shade in portrait...
-        quickQSBrightnessController.setListening(true)
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
-        // ... and rotating to landscape/split shade where slider is visible
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-
-        verify(brightnessController, times(1)).registerCallbacks()
-    }
-
-    @Test
-    fun testCallbacksAreRegisteredOnlyOnceWhenRotatingPhone() {
-        quickQSBrightnessController.setListening(true)
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-
-        verify(brightnessController, times(1)).registerCallbacks()
-    }
-
-    @Test
-    fun testCallbacksAreNotRegisteredWhenSliderNotVisible() {
-        quickQSBrightnessController.setListening(true)
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
-
-        verify(brightnessController, never()).registerCallbacks()
-    }
-
-    @Test
-    fun testMirrorIsSetWhenSliderIsShown() {
-        val mirrorController = mock(BrightnessMirrorController::class.java)
-        quickQSBrightnessController.setMirror(mirrorController)
-        quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-
-        verify(brightnessController).setMirror(mirrorController)
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 59948d3..fb8a6e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -67,8 +67,6 @@
     @Mock
     private lateinit var tileView: QSTileView
     @Mock
-    private lateinit var quickQsBrightnessController: QuickQSBrightnessController
-    @Mock
     private lateinit var footerActionsController: FooterActionsController
     @Captor
     private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener>
@@ -95,7 +93,6 @@
                 uiEventLogger,
                 qsLogger,
                 dumpManager,
-                quickQsBrightnessController,
                 footerActionsController
         )
 
@@ -128,13 +125,11 @@
     }
 
     @Test
-    fun testBrightnessAndFooterVisibilityRefreshedWhenConfigurationChanged() {
+    fun testFooterVisibilityRefreshedWhenConfigurationChanged() {
         // times(2) because both controller and base controller are registering their listeners
         verify(quickQSPanel, times(2)).addOnConfigurationChangedListener(captor.capture())
 
         captor.allValues.forEach { it.onConfigurationChange(Configuration.EMPTY) }
-
-        verify(quickQsBrightnessController).refreshVisibility(anyBoolean())
         // times(2) because footer visibility is also refreshed on controller init
         verify(footerActionsController, times(2)).refreshVisibility(anyBoolean())
     }
diff --git a/services/Android.bp b/services/Android.bp
index 8947393..536dc5d 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -42,7 +42,9 @@
         SYSTEM_OPTIMIZE_JAVA: {
             optimize: {
                 enabled: true,
-                optimize: true,
+                // TODO(b/210510433): Enable optimizations after improving
+                // retracing infra.
+                optimize: false,
                 shrink: true,
                 proguard_flags_files: ["proguard.flags"],
             },
diff --git a/services/autofill/OWNERS b/services/autofill/OWNERS
index c52751d..edfb211 100644
--- a/services/autofill/OWNERS
+++ b/services/autofill/OWNERS
@@ -1 +1 @@
-include /core/java/android/service/autofill/OWNERS
+include /core/java/android/view/autofill/OWNERS
diff --git a/services/core/java/com/android/server/am/DataConnectionStats.java b/services/core/java/com/android/server/am/DataConnectionStats.java
index 6e39a4c..651e98c 100644
--- a/services/core/java/com/android/server/am/DataConnectionStats.java
+++ b/services/core/java/com/android/server/am/DataConnectionStats.java
@@ -73,7 +73,8 @@
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
-        mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler);
+        mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler,
+                Context.RECEIVER_NOT_EXPORTED);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 2c2a2bf..17215e5 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -131,6 +131,7 @@
     private static final int MSG_STOP_SENSOR_LISTENER = 2;
     private static final int MSG_START_SENSOR_LISTENER = 3;
     private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4;
+    private static final int MSG_SENSOR_CHANGED = 5;
 
     private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
@@ -158,6 +159,7 @@
     // These members should only be accessed on the mBgHandler thread.
     private BroadcastReceiver mBroadcastReceiver;
     private SensorListener mSensorListener;
+    private Sensor mLightSensor;
     private SettingsObserver mSettingsObserver;
     private DisplayListener mDisplayListener;
     private boolean mSensorRegistered;
@@ -327,6 +329,14 @@
         m.sendToTarget();
     }
 
+    /**
+     * Updates the light sensor to use.
+     */
+    public void setLightSensor(Sensor lightSensor) {
+        mBgHandler.obtainMessage(MSG_SENSOR_CHANGED, 0 /*unused*/, 0/*unused*/, lightSensor)
+                .sendToTarget();
+    }
+
     private void handleBrightnessChanged(float brightness, boolean userInitiated,
             float powerBrightnessFactor, boolean isUserSetBrightness,
             boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId) {
@@ -428,13 +438,28 @@
         }
     }
 
+    private void handleSensorChanged(Sensor lightSensor) {
+        if (mLightSensor != lightSensor) {
+            mLightSensor = lightSensor;
+            stopSensorListener();
+            synchronized (mDataCollectionLock) {
+                mLastSensorReadings.clear();
+            }
+            // Attempt to restart the sensor listener. It will check to see if it should be running
+            // so there is no need to also check here.
+            startSensorListener();
+        }
+    }
+
     private void startSensorListener() {
         if (!mSensorRegistered
+                && mLightSensor != null
+                && mAmbientBrightnessStatsTracker != null
                 && mInjector.isInteractive(mContext)
                 && mInjector.isBrightnessModeAutomatic(mContentResolver)) {
             mAmbientBrightnessStatsTracker.start();
             mSensorRegistered = true;
-            mInjector.registerSensorListener(mContext, mSensorListener,
+            mInjector.registerSensorListener(mContext, mSensorListener, mLightSensor,
                     mInjector.getBackgroundHandler());
         }
     }
@@ -736,6 +761,7 @@
         pw.println("BrightnessTracker state:");
         synchronized (mDataCollectionLock) {
             pw.println("  mStarted=" + mStarted);
+            pw.println("  mLightSensor=" + mLightSensor);
             pw.println("  mLastBatteryLevel=" + mLastBatteryLevel);
             pw.println("  mLastBrightness=" + mLastBrightness);
             pw.println("  mLastSensorReadings.size=" + mLastSensorReadings.size());
@@ -1017,6 +1043,9 @@
                         disableColorSampling();
                     }
                     break;
+                case MSG_SENSOR_CHANGED:
+                    handleSensorChanged((Sensor) msg.obj);
+                    break;
 
             }
         }
@@ -1045,9 +1074,8 @@
     @VisibleForTesting
     static class Injector {
         public void registerSensorListener(Context context,
-                SensorEventListener sensorListener, Handler handler) {
+                SensorEventListener sensorListener, Sensor lightSensor, Handler handler) {
             SensorManager sensorManager = context.getSystemService(SensorManager.class);
-            Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
             sensorManager.registerListener(sensorListener,
                     lightSensor, SensorManager.SENSOR_DELAY_NORMAL, handler);
         }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index e4cda38..77c1fc0 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -795,7 +795,6 @@
     private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) {
         // All properties that depend on the associated DisplayDevice and the DDC must be
         // updated here.
-        loadAmbientLightSensor();
         loadBrightnessRampRates();
         loadProximitySensor();
         loadNitsRange(mContext.getResources());
@@ -925,6 +924,9 @@
             }
 
             loadAmbientLightSensor();
+            if (mBrightnessTracker != null) {
+                mBrightnessTracker.setLightSensor(mLightSensor);
+            }
 
             if (mAutomaticBrightnessController != null) {
                 mAutomaticBrightnessController.stop();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 211f8d6..f3562d6 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -658,7 +658,14 @@
             return mBuffer.descendingIterator();
         }
 
-        public StatusBarNotification[] getArray(int count, boolean includeSnoozed) {
+        public StatusBarNotification[] getArray(UserManager um, int count, boolean includeSnoozed) {
+            ArrayList<Integer> currentUsers = new ArrayList<>();
+            currentUsers.add(UserHandle.USER_ALL);
+            Binder.withCleanCallingIdentity(() -> {
+                for (int user : um.getProfileIds(ActivityManager.getCurrentUser(), false)) {
+                    currentUsers.add(user);
+                }
+            });
             synchronized (mBufferLock) {
                 if (count == 0) count = mBufferSize;
                 List<StatusBarNotification> a = new ArrayList();
@@ -667,8 +674,10 @@
                 while (iter.hasNext() && i < count) {
                     Pair<StatusBarNotification, Integer> pair = iter.next();
                     if (pair.second != REASON_SNOOZED || includeSnoozed) {
-                        i++;
-                        a.add(pair.first);
+                        if (currentUsers.contains(pair.first.getUserId())) {
+                            i++;
+                            a.add(pair.first);
+                        }
                     }
                 }
                 return a.toArray(new StatusBarNotification[a.size()]);
@@ -4042,22 +4051,32 @@
                     android.Manifest.permission.ACCESS_NOTIFICATIONS,
                     "NotificationManagerService.getActiveNotifications");
 
-            StatusBarNotification[] tmp = null;
+            ArrayList<StatusBarNotification> tmp = new ArrayList<>();
             int uid = Binder.getCallingUid();
 
+            ArrayList<Integer> currentUsers = new ArrayList<>();
+            currentUsers.add(UserHandle.USER_ALL);
+            Binder.withCleanCallingIdentity(() -> {
+                for (int user : mUm.getProfileIds(ActivityManager.getCurrentUser(), false)) {
+                    currentUsers.add(user);
+                }
+            });
+
             // noteOp will check to make sure the callingPkg matches the uid
             if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg,
                     callingAttributionTag, null)
                     == AppOpsManager.MODE_ALLOWED) {
                 synchronized (mNotificationLock) {
-                    tmp = new StatusBarNotification[mNotificationList.size()];
                     final int N = mNotificationList.size();
-                    for (int i=0; i<N; i++) {
-                        tmp[i] = mNotificationList.get(i).getSbn();
+                    for (int i = 0; i < N; i++) {
+                        final StatusBarNotification sbn = mNotificationList.get(i).getSbn();
+                        if (currentUsers.contains(sbn.getUserId())) {
+                            tmp.add(sbn);
+                        }
                     }
                 }
             }
-            return tmp;
+            return tmp.toArray(new StatusBarNotification[tmp.size()]);
         }
 
         /**
@@ -4166,7 +4185,7 @@
                     callingAttributionTag, null)
                     == AppOpsManager.MODE_ALLOWED) {
                 synchronized (mArchive) {
-                    tmp = mArchive.getArray(count, includeSnoozed);
+                    tmp = mArchive.getArray(mUm, count, includeSnoozed);
                 }
             }
             return tmp;
@@ -7695,7 +7714,9 @@
 
             int index = mToastQueue.indexOf(record);
             if (index >= 0) {
-                mToastQueue.remove(index);
+                ToastRecord toast = mToastQueue.remove(index);
+                mWindowManagerInternal.removeWindowToken(
+                        toast.windowToken, true /* removeWindows */, toast.displayId);
             }
             record = (mToastQueue.size() > 0) ? mToastQueue.get(0) : null;
         }
diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java
index 4d19855..acbe04b 100644
--- a/services/core/java/com/android/server/notification/ZenModeFiltering.java
+++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java
@@ -24,11 +24,14 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.media.AudioAttributes;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.provider.Settings.Global;
 import android.service.notification.ZenModeConfig;
 import android.telecom.TelecomManager;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.Slog;
 
@@ -36,6 +39,8 @@
 import com.android.internal.util.NotificationMessagingUtil;
 
 import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
 import java.util.Date;
 
 public class ZenModeFiltering {
@@ -64,13 +69,22 @@
         pw.print(prefix); pw.print("RepeatCallers.mThresholdMinutes=");
         pw.println(REPEAT_CALLERS.mThresholdMinutes);
         synchronized (REPEAT_CALLERS) {
-            if (!REPEAT_CALLERS.mCalls.isEmpty()) {
-                pw.print(prefix); pw.println("RepeatCallers.mCalls=");
-                for (int i = 0; i < REPEAT_CALLERS.mCalls.size(); i++) {
+            if (!REPEAT_CALLERS.mTelCalls.isEmpty()) {
+                pw.print(prefix); pw.println("RepeatCallers.mTelCalls=");
+                for (int i = 0; i < REPEAT_CALLERS.mTelCalls.size(); i++) {
                     pw.print(prefix); pw.print("  ");
-                    pw.print(REPEAT_CALLERS.mCalls.keyAt(i));
+                    pw.print(REPEAT_CALLERS.mTelCalls.keyAt(i));
                     pw.print(" at ");
-                    pw.println(ts(REPEAT_CALLERS.mCalls.valueAt(i)));
+                    pw.println(ts(REPEAT_CALLERS.mTelCalls.valueAt(i)));
+                }
+            }
+            if (!REPEAT_CALLERS.mOtherCalls.isEmpty()) {
+                pw.print(prefix); pw.println("RepeatCallers.mOtherCalls=");
+                for (int i = 0; i < REPEAT_CALLERS.mOtherCalls.size(); i++) {
+                    pw.print(prefix); pw.print("  ");
+                    pw.print(REPEAT_CALLERS.mOtherCalls.keyAt(i));
+                    pw.print(" at ");
+                    pw.println(ts(REPEAT_CALLERS.mOtherCalls.valueAt(i)));
                 }
             }
         }
@@ -312,34 +326,39 @@
     }
 
     private static class RepeatCallers {
-        // Person : time
-        private final ArrayMap<String, Long> mCalls = new ArrayMap<>();
+        // We keep a separate map per uri scheme to do more generous number-matching
+        // handling on telephone numbers specifically. For other inputs, we
+        // simply match directly on the string.
+        private final ArrayMap<String, Long> mTelCalls = new ArrayMap<>();
+        private final ArrayMap<String, Long> mOtherCalls = new ArrayMap<>();
         private int mThresholdMinutes;
 
         private synchronized void recordCall(Context context, Bundle extras) {
             setThresholdMinutes(context);
             if (mThresholdMinutes <= 0 || extras == null) return;
-            final String peopleString = peopleString(extras);
-            if (peopleString == null) return;
+            final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras);
+            if (extraPeople == null || extraPeople.length == 0) return;
             final long now = System.currentTimeMillis();
-            cleanUp(mCalls, now);
-            mCalls.put(peopleString, now);
+            cleanUp(mTelCalls, now);
+            cleanUp(mOtherCalls, now);
+            recordCallers(extraPeople, now);
         }
 
         private synchronized boolean isRepeat(Context context, Bundle extras) {
             setThresholdMinutes(context);
             if (mThresholdMinutes <= 0 || extras == null) return false;
-            final String peopleString = peopleString(extras);
-            if (peopleString == null) return false;
+            final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras);
+            if (extraPeople == null || extraPeople.length == 0) return false;
             final long now = System.currentTimeMillis();
-            cleanUp(mCalls, now);
-            return mCalls.containsKey(peopleString);
+            cleanUp(mTelCalls, now);
+            cleanUp(mOtherCalls, now);
+            return checkCallers(context, extraPeople);
         }
 
         private synchronized void cleanUp(ArrayMap<String, Long> calls, long now) {
             final int N = calls.size();
             for (int i = N - 1; i >= 0; i--) {
-                final long time = mCalls.valueAt(i);
+                final long time = calls.valueAt(i);
                 if (time > now || (now - time) > mThresholdMinutes * 1000 * 60) {
                     calls.removeAt(i);
                 }
@@ -353,21 +372,65 @@
             }
         }
 
-        private static String peopleString(Bundle extras) {
-            final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras);
-            if (extraPeople == null || extraPeople.length == 0) return null;
-            final StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < extraPeople.length; i++) {
-                String extraPerson = extraPeople[i];
-                if (extraPerson == null) continue;
-                extraPerson = extraPerson.trim();
-                if (extraPerson.isEmpty()) continue;
-                if (sb.length() > 0) {
-                    sb.append('|');
+        private synchronized void recordCallers(String[] people, long now) {
+            for (int i = 0; i < people.length; i++) {
+                String person = people[i];
+                if (person == null) continue;
+                final Uri uri = Uri.parse(person);
+                if ("tel".equals(uri.getScheme())) {
+                    String tel = uri.getSchemeSpecificPart();
+                    // while ideally we should not need to do this, sometimes we have seen tel
+                    // numbers given in a url-encoded format
+                    try {
+                        tel = URLDecoder.decode(tel, "UTF-8");
+                    } catch (UnsupportedEncodingException e) {
+                        // ignore, keep the original tel string
+                        Slog.w(TAG, "unsupported encoding in tel: uri input");
+                    }
+                    mTelCalls.put(tel, now);
+                } else {
+                    // for non-tel calls, store the entire string, uri-component and all
+                    mOtherCalls.put(person, now);
                 }
-                sb.append(extraPerson);
             }
-            return sb.length() == 0 ? null : sb.toString();
+        }
+
+        private synchronized boolean checkCallers(Context context, String[] people) {
+            // get the default country code for checking telephone numbers
+            final String defaultCountryCode =
+                    context.getSystemService(TelephonyManager.class).getNetworkCountryIso();
+            for (int i = 0; i < people.length; i++) {
+                String person = people[i];
+                if (person == null) continue;
+                final Uri uri = Uri.parse(person);
+                if ("tel".equals(uri.getScheme())) {
+                    String number = uri.getSchemeSpecificPart();
+                    if (mTelCalls.containsKey(number)) {
+                        // check directly via map first
+                        return true;
+                    } else {
+                        // see if a number that matches via areSameNumber exists
+                        String numberToCheck = number;
+                        try {
+                            numberToCheck = URLDecoder.decode(number, "UTF-8");
+                        } catch (UnsupportedEncodingException e) {
+                            // ignore, continue to use the original string
+                            Slog.w(TAG, "unsupported encoding in tel: uri input");
+                        }
+                        for (String prev : mTelCalls.keySet()) {
+                            if (PhoneNumberUtils.areSamePhoneNumber(
+                                    numberToCheck, prev, defaultCountryCode)) {
+                                return true;
+                            }
+                        }
+                    }
+                } else {
+                    if (mOtherCalls.containsKey(person)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
         }
     }
 
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index a17e792..30e2617 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -146,7 +146,7 @@
         filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
         filter.addAction(ACTION_MULTI_SIM_CONFIG_CHANGED);
 
-        mContext.registerReceiver(this, filter, null, mHandler);
+        mContext.registerReceiver(this, filter, null, mHandler, Context.RECEIVER_NOT_EXPORTED);
         mSubscriptionManager.addOnSubscriptionsChangedListener(
                 executor, mSubscriptionChangedListener);
         mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener);
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 8b80b4a..597f7f2 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -78,6 +78,7 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.util.ArraySet;
 import android.util.Slog;
 
@@ -163,6 +164,14 @@
 public class VcnGatewayConnection extends StateMachine {
     private static final String TAG = VcnGatewayConnection.class.getSimpleName();
 
+    // Matches DataConnection.NETWORK_TYPE private constant, and magic string from
+    // ConnectivityManager#getNetworkTypeName()
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final String NETWORK_INFO_NETWORK_TYPE_STRING = "MOBILE";
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final String NETWORK_INFO_EXTRA_INFO = "VCN";
+
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     static final InetAddress DUMMY_ADDR = InetAddresses.parseNumericAddress("192.0.2.0");
 
@@ -1631,6 +1640,12 @@
             final NetworkAgentConfig nac =
                     new NetworkAgentConfig.Builder()
                             .setLegacyType(ConnectivityManager.TYPE_MOBILE)
+                            .setLegacyTypeName(NETWORK_INFO_NETWORK_TYPE_STRING)
+                            .setLegacySubType(TelephonyManager.NETWORK_TYPE_UNKNOWN)
+                            .setLegacySubTypeName(
+                                    TelephonyManager.getNetworkTypeName(
+                                            TelephonyManager.NETWORK_TYPE_UNKNOWN))
+                            .setLegacyExtraInfo(NETWORK_INFO_EXTRA_INFO)
                             .build();
 
             final VcnNetworkAgent agent =
diff --git a/services/core/jni/BroadcastRadio/types.h b/services/core/jni/BroadcastRadio/types.h
index 910bb7c..4d286bf 100644
--- a/services/core/jni/BroadcastRadio/types.h
+++ b/services/core/jni/BroadcastRadio/types.h
@@ -30,13 +30,13 @@
 // Keep in sync with STATUS_* constants from RadioManager.java.
 enum class Status : jint {
     OK = 0,
-    ERROR = -0x80000000ll,  // Integer.MIN_VALUE
+    ERROR = -0x80000000LL,   // Integer.MIN_VALUE
     PERMISSION_DENIED = -1,  // -EPERM
-    NO_INIT = -19,  // -ENODEV
-    BAD_VALUE = -22,  // -EINVAL
-    DEAD_OBJECT = -32,  // -EPIPE
-    INVALID_OPERATION = -38,  // -ENOSYS
-    TIMED_OUT = -110,  // -ETIMEDOUT
+    NO_INIT = -19,           // -ENODEV
+    BAD_VALUE = -22,         // -EINVAL
+    DEAD_OBJECT = -32,       // -EPIPE
+    INVALID_OPERATION = -38, // -ENOSYS
+    TIMED_OUT = -110,        // -ETIMEDOUT
 };
 
 // Keep in sync with REGION_* constants from RadioManager.java.
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index f8a8168..39cbaf7 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -102,15 +102,10 @@
     }
 }
 
-static int deleteTagData(JNIEnv* /* env */, jclass /* clazz */, jint uid) {
-    return qtaguid_deleteTagData(0, uid);
-}
-
 static const JNINativeMethod gMethods[] = {
         {"nativeGetTotalStat", "(I)J", (void*)getTotalStat},
         {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat},
         {"nativeGetUidStat", "(II)J", (void*)getUidStat},
-        {"nativeDeleteTagData", "(I)I", (void*)deleteTagData},
 };
 
 int register_android_server_net_NetworkStatsService(JNIEnv* env) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 85e08eb..dabdff2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -10768,7 +10768,7 @@
     }
 
     @Override
-    public void resetNewUserDisclaimer() {
+    public void acknowledgeNewUserDisclaimer() {
         CallerIdentity callerIdentity = getCallerIdentity();
         canManageUsers(callerIdentity);
 
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index bdf94f3..356600d 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -33,6 +33,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ParceledListSlice;
 import android.database.ContentObserver;
+import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.display.AmbientBrightnessDayStats;
@@ -42,6 +43,7 @@
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayedContentSample;
 import android.hardware.display.DisplayedContentSamplingAttributes;
+import android.hardware.input.InputSensorInfo;
 import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -63,6 +65,8 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -84,8 +88,11 @@
     private static final String DEFAULT_DISPLAY_ID = "123";
     private static final float FLOAT_DELTA = 0.01f;
 
+    @Mock private InputSensorInfo mInputSensorInfoMock;
+
     private BrightnessTracker mTracker;
     private TestInjector mInjector;
+    private Sensor mLightSensorFake;
 
     private static Object sHandlerLock = new Object();
     private static Handler sHandler;
@@ -108,9 +115,12 @@
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
         mInjector = new TestInjector(ensureHandler());
+        mLightSensorFake = new Sensor(mInputSensorInfoMock);
 
         mTracker = new BrightnessTracker(InstrumentationRegistry.getContext(), mInjector);
+        mTracker.setLightSensor(mLightSensorFake);
         mDefaultNightModeColorTemperature =
                 InstrumentationRegistry.getContext().getResources().getInteger(
                 R.integer.config_nightDisplayColorTemperatureDefault);
@@ -834,6 +844,47 @@
         mTracker.stop();
     }
 
+    @Test
+    public void testLightSensorChange() {
+        // verify the tracker started correctly and a listener registered
+        startTracker(mTracker);
+        assertNotNull(mInjector.mSensorListener);
+        assertEquals(mInjector.mLightSensor, mLightSensorFake);
+
+        // Setting the sensor to null should stop the registered listener.
+        mTracker.setLightSensor(null);
+        mInjector.waitForHandler();
+        assertNull(mInjector.mSensorListener);
+        assertNull(mInjector.mLightSensor);
+
+        // Resetting sensor should start listener again
+        mTracker.setLightSensor(mLightSensorFake);
+        mInjector.waitForHandler();
+        assertNotNull(mInjector.mSensorListener);
+        assertEquals(mInjector.mLightSensor, mLightSensorFake);
+
+        Sensor secondSensor = new Sensor(mInputSensorInfoMock);
+        // Setting a different listener should keep things working
+        mTracker.setLightSensor(secondSensor);
+        mInjector.waitForHandler();
+        assertNotNull(mInjector.mSensorListener);
+        assertEquals(mInjector.mLightSensor, secondSensor);
+    }
+
+    @Test
+    public void testSetLightSensorDoesntStartListener() {
+        mTracker.setLightSensor(mLightSensorFake);
+        assertNull(mInjector.mSensorListener);
+    }
+
+    @Test
+    public void testNullLightSensorWontRegister() {
+        mTracker.setLightSensor(null);
+        startTracker(mTracker);
+        assertNull(mInjector.mSensorListener);
+        assertNull(mInjector.mLightSensor);
+    }
+
     private InputStream getInputStream(String data) {
         return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
     }
@@ -924,6 +975,7 @@
 
     private class TestInjector extends BrightnessTracker.Injector {
         SensorEventListener mSensorListener;
+        Sensor mLightSensor;
         BroadcastReceiver mBroadcastReceiver;
         DisplayManager.DisplayListener mDisplayListener;
         Map<String, Integer> mSecureIntSettings = new HashMap<>();
@@ -974,14 +1026,16 @@
 
         @Override
         public void registerSensorListener(Context context,
-                SensorEventListener sensorListener, Handler handler) {
+                SensorEventListener sensorListener, Sensor lightSensor, Handler handler) {
             mSensorListener = sensorListener;
+            mLightSensor = lightSensor;
         }
 
         @Override
         public void unregisterSensorListener(Context context,
                 SensorEventListener sensorListener) {
             mSensorListener = null;
+            mLightSensor = null;
         }
 
         @Override
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java
index 1126e1e..4b6183d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java
@@ -15,16 +15,22 @@
  */
 package com.android.server.notification;
 
+import static android.os.UserHandle.USER_ALL;
 import static android.os.UserHandle.USER_CURRENT;
+import static android.os.UserHandle.USER_NULL;
 import static android.os.UserHandle.USER_SYSTEM;
 import static android.service.notification.NotificationListenerService.REASON_CANCEL;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.when;
 
 import android.app.Notification;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.service.notification.StatusBarNotification;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -35,6 +41,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
@@ -51,6 +58,8 @@
     private static final int SIZE = 5;
 
     private NotificationManagerService.Archive mArchive;
+    @Mock
+    private UserManager mUm;
 
     @Before
     public void setUp() {
@@ -59,6 +68,9 @@
         mArchive = new NotificationManagerService.Archive(SIZE);
         mArchive.updateHistoryEnabled(USER_SYSTEM, true);
         mArchive.updateHistoryEnabled(USER_CURRENT, true);
+
+        when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(
+                new int[] {USER_CURRENT, USER_SYSTEM});
     }
 
     private StatusBarNotification getNotification(String pkg, int id, UserHandle user) {
@@ -70,7 +82,6 @@
                 pkg, pkg, id, null, 0, 0, n, user, null, System.currentTimeMillis());
     }
 
-
     @Test
     public void testRecordAndRead() {
         List<String> expected = new ArrayList<>();
@@ -81,7 +92,7 @@
             mArchive.record(sbn, REASON_CANCEL);
         }
 
-        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
         assertThat(actual).hasSize(expected.size());
         for (StatusBarNotification sbn : actual) {
             assertThat(expected).contains(sbn.getKey());
@@ -89,6 +100,22 @@
     }
 
     @Test
+    public void testCrossUser() {
+        mArchive.record(getNotification("pkg", 1, UserHandle.of(USER_SYSTEM)), REASON_CANCEL);
+        mArchive.record(getNotification("pkg", 2, UserHandle.of(USER_CURRENT)), REASON_CANCEL);
+        mArchive.record(getNotification("pkg", 3, UserHandle.of(USER_ALL)), REASON_CANCEL);
+        mArchive.record(getNotification("pkg", 4, UserHandle.of(USER_NULL)), REASON_CANCEL);
+
+        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
+        assertThat(actual).hasSize(3);
+        for (StatusBarNotification sbn : actual) {
+            if (sbn.getUserId() == USER_NULL) {
+                fail("leaked notification from wrong user");
+            }
+        }
+    }
+
+    @Test
     public void testRecordAndRead_overLimit() {
         List<String> expected = new ArrayList<>();
         for (int i = 0; i < (SIZE * 2); i++) {
@@ -99,7 +126,8 @@
             }
         }
 
-        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray((SIZE * 2), true));
+        List<StatusBarNotification> actual = Arrays.asList(
+                mArchive.getArray(mUm, (SIZE * 2), true));
         assertThat(actual).hasSize(expected.size());
         for (StatusBarNotification sbn : actual) {
             assertThat(expected).contains(sbn.getKey());
@@ -119,7 +147,7 @@
             }
         }
 
-        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
         assertThat(actual).hasSize(expected.size());
         for (StatusBarNotification sbn : actual) {
             assertThat(expected).contains(sbn.getKey());
@@ -140,7 +168,7 @@
         }
         mArchive.updateHistoryEnabled(USER_CURRENT, false);
 
-        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
         assertThat(actual).hasSize(expected.size());
         for (StatusBarNotification sbn : actual) {
             assertThat(expected).contains(sbn.getKey());
@@ -165,7 +193,7 @@
         }
         mArchive.removeChannelNotifications("pkg", USER_CURRENT, "test0");
         mArchive.removeChannelNotifications("pkg", USER_CURRENT, "test" + (SIZE - 2));
-        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
         assertThat(actual).hasSize(expected.size());
         for (StatusBarNotification sbn : actual) {
             assertThat(expected).contains(sbn.getKey());
@@ -215,7 +243,7 @@
             fail("Concurrent modification exception");
         }
 
-        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+        List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
         assertThat(actual).hasSize(expected.size());
         for (StatusBarNotification sbn : actual) {
             assertThat(expected).contains(sbn.getKey());
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index e98d077..b98401e 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -60,6 +60,7 @@
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -475,6 +476,7 @@
         when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
         when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
         mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
+        when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0});
 
         // write to a test file; the system file isn't readable from tests
         mFile = new File(mContext.getCacheDir(), "test.xml");
@@ -5572,6 +5574,39 @@
     }
 
     @Test
+    public void testRateLimitedToasts_windowsRemoved() throws Exception {
+        final String testPackage = "testPackageName";
+        assertEquals(0, mService.mToastQueue.size());
+        mService.isSystemUid = false;
+        setToastRateIsWithinQuota(false); // rate limit reached
+        setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
+        setAppInForegroundForToasts(mUid, false);
+
+        // package is not suspended
+        when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
+                .thenReturn(false);
+
+        Binder token = new Binder();
+        INotificationManager nmService = (INotificationManager) mService.mService;
+
+        nmService.enqueueTextToast(testPackage, token, "Text", 2000, 0, null);
+
+        // window token was added when enqueued
+        ArgumentCaptor<Binder> binderCaptor =
+                ArgumentCaptor.forClass(Binder.class);
+        verify(mWindowManagerInternal).addWindowToken(binderCaptor.capture(),
+                eq(TYPE_TOAST), anyInt(), eq(null));
+
+        // but never shown
+        verify(mStatusBar, times(0))
+                .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any());
+
+        // and removed when rate limited
+        verify(mWindowManagerInternal)
+                .removeWindowToken(eq(binderCaptor.getValue()), eq(true), anyInt());
+    }
+
+    @Test
     public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws
             Exception {
         final String testPackage = "testPackageName";
@@ -6970,8 +7005,9 @@
         waitForIdle();
 
         // A notification exists for the given record
-        StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
-        assertEquals(1, notifsBefore.length);
+        List<StatusBarNotification> notifsBefore =
+                mBinderService.getAppActiveNotifications(PKG, nr.getSbn().getUserId()).getList();
+        assertEquals(1, notifsBefore.size());
 
         reset(mPackageManager);
 
@@ -8289,4 +8325,33 @@
         assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001)));
         assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("test", 1002)));
     }
+
+    @Test
+    public void testGetActiveNotification_filtersUsers() throws Exception {
+        when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10});
+
+        NotificationRecord nr0 =
+                generateNotificationRecord(mTestNotificationChannel, 0);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0",
+                nr0.getSbn().getId(), nr0.getSbn().getNotification(), nr0.getSbn().getUserId());
+
+        NotificationRecord nr10 =
+                generateNotificationRecord(mTestNotificationChannel, 10);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10",
+                nr10.getSbn().getId(), nr10.getSbn().getNotification(), nr10.getSbn().getUserId());
+
+        NotificationRecord nr11 =
+                generateNotificationRecord(mTestNotificationChannel, 11);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11",
+                nr11.getSbn().getId(), nr11.getSbn().getNotification(), nr11.getSbn().getUserId());
+        waitForIdle();
+
+        StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
+        assertEquals(2, notifs.length);
+        for (StatusBarNotification sbn : notifs) {
+            if (sbn.getUserId() == 11) {
+                fail("leaked data across users");
+            }
+        }
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
index fb15088..0f18cc6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
@@ -17,7 +17,6 @@
 package com.android.server.notification;
 
 import static android.app.Notification.CATEGORY_CALL;
-import static android.app.Notification.CATEGORY_MESSAGE;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
 import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
@@ -25,6 +24,7 @@
 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
 import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
@@ -43,8 +43,10 @@
 import android.app.NotificationChannel;
 import android.app.NotificationManager.Policy;
 import android.media.AudioAttributes;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
+import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -68,10 +70,15 @@
     private NotificationMessagingUtil mMessagingUtil;
     private ZenModeFiltering mZenModeFiltering;
 
+    @Mock private TelephonyManager mTelephonyManager;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mZenModeFiltering = new ZenModeFiltering(mContext, mMessagingUtil);
+
+        // for repeat callers / matchesCallFilter
+        mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
     }
 
     private NotificationRecord getNotificationRecord() {
@@ -95,6 +102,23 @@
         return r;
     }
 
+    private Bundle makeExtrasBundleWithPeople(String[] people) {
+        Bundle extras = new Bundle();
+        extras.putObject(Notification.EXTRA_PEOPLE_LIST, people);
+        return extras;
+    }
+
+    private NotificationRecord getNotificationRecordWithPeople(String[] people) {
+        // set up notification record
+        NotificationRecord r = mock(NotificationRecord.class);
+        StatusBarNotification sbn = mock(StatusBarNotification.class);
+        Notification notification = mock(Notification.class);
+        notification.extras = makeExtrasBundleWithPeople(people);
+        when(sbn.getNotification()).thenReturn(notification);
+        when(r.getSbn()).thenReturn(sbn);
+        return r;
+    }
+
     @Test
     public void testIsMessage() {
         NotificationRecord r = getNotificationRecord();
@@ -309,4 +333,111 @@
 
         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
     }
+
+    @Test
+    public void testMatchesCallFilter_repeatCallers_directMatch() {
+        // after calls given an email with an exact string match, make sure that
+        // matchesCallFilter returns the right thing
+        String[] mailSource = new String[]{"mailto:hello.world"};
+        mZenModeFiltering.recordCall(getNotificationRecordWithPeople(mailSource));
+
+        // set up policy to only allow repeat callers
+        Policy policy = new Policy(
+                PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
+
+        // check whether matchesCallFilter returns the right thing
+        Bundle inputMatches = makeExtrasBundleWithPeople(new String[]{"mailto:hello.world"});
+        Bundle inputWrong = makeExtrasBundleWithPeople(new String[]{"mailto:nope"});
+        assertTrue(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                policy, UserHandle.SYSTEM,
+                inputMatches, null, 0, 0));
+        assertFalse(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                policy, UserHandle.SYSTEM,
+                inputWrong, null, 0, 0));
+    }
+
+    @Test
+    public void testMatchesCallFilter_repeatCallers_telephoneVariants() {
+        // set up telephony manager behavior
+        when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
+
+        String[] telSource = new String[]{"tel:+1-617-555-1212"};
+        mZenModeFiltering.recordCall(getNotificationRecordWithPeople(telSource));
+
+        // set up policy to only allow repeat callers
+        Policy policy = new Policy(
+                PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
+
+        // cases to test:
+        //   - identical number
+        //   - same number, different formatting
+        //   - different number
+        //   - garbage
+        Bundle identical = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"});
+        Bundle same = makeExtrasBundleWithPeople(new String[]{"tel:16175551212"});
+        Bundle different = makeExtrasBundleWithPeople(new String[]{"tel:123-456-7890"});
+        Bundle garbage = makeExtrasBundleWithPeople(new String[]{"asdfghjkl;"});
+
+        assertTrue("identical numbers should match",
+                ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                policy, UserHandle.SYSTEM,
+                identical, null, 0, 0));
+        assertTrue("equivalent but non-identical numbers should match",
+                ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                policy, UserHandle.SYSTEM,
+                same, null, 0, 0));
+        assertFalse("non-equivalent numbers should not match",
+                ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                policy, UserHandle.SYSTEM,
+                different, null, 0, 0));
+        assertFalse("non-tel strings should not match",
+                ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                policy, UserHandle.SYSTEM,
+                garbage, null, 0, 0));
+    }
+
+    @Test
+    public void testMatchesCallFilter_repeatCallers_urlEncodedTels() {
+        // this is not intended to be a supported case but is one that we have seen
+        // sometimes in the wild, so make sure we handle url-encoded telephone numbers correctly
+        // when somebody provides one.
+
+        // set up telephony manager behavior
+        when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
+
+        String[] telSource = new String[]{"tel:%2B16175551212"};
+        mZenModeFiltering.recordCall(getNotificationRecordWithPeople(telSource));
+
+        // set up policy to only allow repeat callers
+        Policy policy = new Policy(
+                PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
+
+        // test cases for various forms of the same phone number and different ones
+        Bundle same1 = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"});
+        Bundle same2 = makeExtrasBundleWithPeople(new String[]{"tel:%2B1-617-555-1212"});
+        Bundle same3 = makeExtrasBundleWithPeople(new String[]{"tel:6175551212"});
+        Bundle different1 = makeExtrasBundleWithPeople(new String[]{"tel:%2B16175553434"});
+        Bundle different2 = makeExtrasBundleWithPeople(new String[]{"tel:+16175553434"});
+
+        assertTrue("same number should match",
+                ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                        policy, UserHandle.SYSTEM,
+                        same1, null, 0, 0));
+        assertTrue("same number should match",
+                ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                        policy, UserHandle.SYSTEM,
+                        same2, null, 0, 0));
+        assertTrue("same number should match",
+                ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                        policy, UserHandle.SYSTEM,
+                        same3, null, 0, 0));
+        assertFalse("different number should not match",
+                ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                        policy, UserHandle.SYSTEM,
+                        different1, null, 0, 0));
+        assertFalse("different number should not match",
+                ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                        policy, UserHandle.SYSTEM,
+                        different2, null, 0, 0));
+    }
 }
diff --git a/services/translation/OWNERS b/services/translation/OWNERS
index a1e663a..440f9a8 100644
--- a/services/translation/OWNERS
+++ b/services/translation/OWNERS
@@ -1,8 +1,3 @@
 # Bug component: 994311
 
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+include /core/java/android/view/translation/OWNERS
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 3882acf..5ada2a4 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -489,6 +489,7 @@
 
         // current USB state
         private boolean mHostConnected;
+        private boolean mUsbAccessoryConnected;
         private boolean mSourcePower;
         private boolean mSinkPower;
         private boolean mConfigured;
@@ -958,10 +959,10 @@
                     break;
                 case MSG_UPDATE_HOST_STATE:
                     Iterator devices = (Iterator) msg.obj;
-                    boolean connected = (msg.arg1 == 1);
+                    mUsbAccessoryConnected = (msg.arg1 == 1);
 
                     if (DEBUG) {
-                        Slog.i(TAG, "HOST_STATE connected:" + connected);
+                        Slog.i(TAG, "HOST_STATE connected:" + mUsbAccessoryConnected);
                     }
 
                     mHideUsbNotification = false;
@@ -1215,7 +1216,7 @@
             } else if (mSourcePower) {
                 titleRes = com.android.internal.R.string.usb_supplying_notification_title;
                 id = SystemMessage.NOTE_USB_SUPPLYING;
-            } else if (mHostConnected && mSinkPower && mUsbCharging) {
+            } else if (mHostConnected && mSinkPower && (mUsbCharging || mUsbAccessoryConnected)) {
                 titleRes = com.android.internal.R.string.usb_charging_notification_title;
                 id = SystemMessage.NOTE_USB_CHARGING;
             }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ab8867f..ef847b6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -4619,6 +4619,15 @@
                 KEY_PREFIX + "enable_presence_group_subscribe_bool";
 
         /**
+         * Flag indicating whether or not to use SIP URI when send a presence subscribe.
+         * When {@code true}, the device sets the To and Contact header to be SIP URI using
+         * the TelephonyManager#getIsimDomain" API.
+         * If {@code false}, the device uses a TEL URI.
+         */
+        public static final String KEY_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL =
+                KEY_PREFIX + "use_sip_uri_for_presence_subscribe_bool";
+
+        /**
          * An integer key associated with the period of time in seconds the non-rcs capability
          * information of each contact is cached on the device.
          * <p>
@@ -4800,6 +4809,7 @@
             defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false);
             defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false);
             defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, false);
+            defaults.putBoolean(KEY_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL, false);
             defaults.putInt(KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT, 30 * 24 * 60 * 60);
             defaults.putBoolean(KEY_RCS_REQUEST_FORBIDDEN_BY_SIP_489_BOOL, false);
             defaults.putLong(KEY_RCS_REQUEST_RETRY_INTERVAL_MILLIS_LONG, 20 * 60 * 1000);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 846e6f3..9fd2ae4 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -767,6 +768,10 @@
      *
      * @return long name of operator, null if unregistered or unknown
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public String getOperatorAlphaLong() {
         return mOperatorAlphaLong;
     }
@@ -782,6 +787,10 @@
      * @return long name of operator
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "Use {@link #getOperatorAlphaLong} instead.")
     public String getVoiceOperatorAlphaLong() {
@@ -800,6 +809,10 @@
      *
      * @return short name of operator, null if unregistered or unknown
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public String getOperatorAlphaShort() {
         return mOperatorAlphaShort;
     }
@@ -815,6 +828,10 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
     public String getVoiceOperatorAlphaShort() {
@@ -832,6 +849,10 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
     public String getDataOperatorAlphaShort() {
@@ -853,6 +874,10 @@
      * @return name of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public String getOperatorAlpha() {
         if (TextUtils.isEmpty(mOperatorAlphaLong)) {
             return mOperatorAlphaShort;
@@ -878,6 +903,10 @@
      * The country code can be decoded using
      * {@link com.android.internal.telephony.MccTable#countryCodeForMcc(int)}.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public String getOperatorNumeric() {
         return mOperatorNumeric;
     }
@@ -893,6 +922,10 @@
      * @return numeric format of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getVoiceOperatorNumeric() {
         return mOperatorNumeric;
@@ -909,6 +942,10 @@
      * @return numeric format of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "Use {@link #getOperatorNumeric} instead.")
     public String getDataOperatorNumeric() {
@@ -1758,8 +1795,17 @@
     /**
      * Get the CDMA NID (Network Identification Number), a number uniquely identifying a network
      * within a wireless system. (Defined in 3GPP2 C.S0023 3.4.8)
+     *
+     * <p>Require at least {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. Otherwise return
+     * {@link #UNKNOWN_ID}.
+     *
      * @return The CDMA NID or {@link #UNKNOWN_ID} if not available.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public int getCdmaNetworkId() {
         return this.mNetworkId;
     }
@@ -1767,8 +1813,17 @@
     /**
      * Get the CDMA SID (System Identification Number), a number uniquely identifying a wireless
      * system. (Defined in 3GPP2 C.S0023 3.4.8)
+     *
+     * <p>Require at least {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. Otherwise return
+     * {@link #UNKNOWN_ID}.
+     *
      * @return The CDMA SID or {@link #UNKNOWN_ID} if not available.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public int getCdmaSystemId() {
         return this.mSystemId;
     }
@@ -2069,6 +2124,8 @@
         state.mOperatorAlphaLong = null;
         state.mOperatorAlphaShort = null;
         state.mOperatorNumeric = null;
+        state.mSystemId = UNKNOWN_ID;
+        state.mNetworkId = UNKNOWN_ID;
 
         return state;
     }
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index 9112118..9c36db8 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -221,6 +221,15 @@
         }
 
         /**
+         * Set the entity URI related to the contact whose capabilities were requested.
+         * @param entityUri the 'pres' URL of the PRESENTITY publishing presence document.
+         */
+        public @NonNull PresenceBuilder setEntityUri(@NonNull Uri entityUri) {
+            mCapabilities.mEntityUri = entityUri;
+            return this;
+        }
+
+        /**
          * @return the RcsContactUceCapability instance.
          */
         public @NonNull RcsContactUceCapability build() {
@@ -232,6 +241,7 @@
     private @SourceType int mSourceType;
     private @CapabilityMechanism int mCapabilityMechanism;
     private @RequestResult int mRequestResult;
+    private Uri mEntityUri;
 
     private final Set<String> mFeatureTags = new HashSet<>();
     private final List<RcsContactPresenceTuple> mPresenceTuples = new ArrayList<>();
@@ -248,6 +258,7 @@
         mCapabilityMechanism = in.readInt();
         mSourceType = in.readInt();
         mRequestResult = in.readInt();
+        mEntityUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
         List<String> featureTagList = new ArrayList<>();
         in.readStringList(featureTagList);
         mFeatureTags.addAll(featureTagList);
@@ -260,6 +271,7 @@
         out.writeInt(mCapabilityMechanism);
         out.writeInt(mSourceType);
         out.writeInt(mRequestResult);
+        out.writeParcelable(mEntityUri, flags);
         out.writeStringList(new ArrayList<>(mFeatureTags));
         out.writeParcelableList(mPresenceTuples, flags);
     }
@@ -361,6 +373,15 @@
         return mContactUri;
     }
 
+    /**
+     * Retrieve the entity URI of the contact whose presence information is being requested for.
+     * @return the URI representing the 'pres' URL of the PRESENTITY publishing presence document
+     * or {@code null} if the entity uri does not exist in the presence document.
+     */
+    public @Nullable Uri getEntityUri() {
+        return mEntityUri;
+    }
+
     @Override
     public String toString() {
         StringBuilder builder = new StringBuilder("RcsContactUceCapability");
@@ -382,6 +403,13 @@
         builder.append(mSourceType);
         builder.append(", requestResult=");
         builder.append(mRequestResult);
+        if (Build.IS_ENG) {
+            builder.append("entity uri=");
+            builder.append(mEntityUri != null ? mEntityUri : "null");
+        } else {
+            builder.append("entity uri (isNull)=");
+            builder.append(mEntityUri != null ? "XXX" : "null");
+        }
 
         if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) {
             builder.append(", presenceTuples={");
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 978bf3e..7b1f7a5 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -174,7 +174,7 @@
 
     private IntentFilter getIntentFilter() {
         final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
-        verify(mContext).registerReceiver(any(), captor.capture(), any(), any());
+        verify(mContext).registerReceiver(any(), captor.capture(), any(), any(), anyInt());
 
         return captor.getValue();
     }
@@ -258,7 +258,8 @@
                         eq(mTelephonySubscriptionTracker),
                         any(IntentFilter.class),
                         any(),
-                        eq(mHandler));
+                        eq(mHandler),
+                        eq(Context.RECEIVER_NOT_EXPORTED));
         final IntentFilter filter = getIntentFilter();
         assertEquals(2, filter.countActions());
         assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED));
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index e547400..4cfa93b 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -307,7 +307,10 @@
                         ncCaptor.capture(),
                         lpCaptor.capture(),
                         any(),
-                        argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE),
+                        // Subtype integer/name and extras do not have getters; cannot be tested.
+                        argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE
+                                && nac.getLegacyTypeName().equals(
+                                        VcnGatewayConnection.NETWORK_INFO_NETWORK_TYPE_STRING)),
                         any(),
                         any(),
                         any());