Merge "Add more files as dexopt related files." into tm-dev
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index a8dd752..dfa1442 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -548,7 +548,7 @@
             out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId()));
             out.attribute(null, "uid", Integer.toString(jobStatus.getUid()));
             out.attribute(null, "bias", String.valueOf(jobStatus.getBias()));
-            out.attribute(null, "priority", String.valueOf(jobStatus.getEffectivePriority()));
+            out.attribute(null, "priority", String.valueOf(jobStatus.getJob().getPriority()));
             out.attribute(null, "flags", String.valueOf(jobStatus.getFlags()));
             if (jobStatus.getInternalFlags() != 0) {
                 out.attribute(null, "internalFlags", String.valueOf(jobStatus.getInternalFlags()));
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 849354b..04f96de 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -78,6 +78,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
 import android.database.ContentObserver;
 import android.hardware.display.DisplayManager;
 import android.net.NetworkScoreManager;
@@ -219,7 +220,8 @@
 
     private static final int HEADLESS_APP_CHECK_FLAGS =
             PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-                    | PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS;
+                    | PackageManager.MATCH_DISABLED_COMPONENTS
+                    | PackageManager.MATCH_SYSTEM_ONLY;
 
     // To name the lock for stack traces
     static class Lock {}
@@ -253,7 +255,7 @@
     private final SparseArray<Set<String>> mActiveAdminApps = new SparseArray<>();
 
     /**
-     * Set of system apps that are headless (don't have any declared activities, enabled or
+     * Set of system apps that are headless (don't have any "front door" activities, enabled or
      * disabled). Presence in this map indicates that the app is a headless system app.
      */
     @GuardedBy("mHeadlessSystemApps")
@@ -1942,7 +1944,7 @@
         try {
             PackageInfo pi = mPackageManager.getPackageInfoAsUser(
                     packageName, HEADLESS_APP_CHECK_FLAGS, userId);
-            evaluateSystemAppException(pi);
+            maybeUpdateHeadlessSystemAppCache(pi);
         } catch (PackageManager.NameNotFoundException e) {
             synchronized (mHeadlessSystemApps) {
                 mHeadlessSystemApps.remove(packageName);
@@ -1950,19 +1952,31 @@
         }
     }
 
-    /** Returns true if the exception status changed. */
-    private boolean evaluateSystemAppException(@Nullable PackageInfo pkgInfo) {
+    /**
+     * Update the "headless system app" cache.
+     *
+     * @return true if the cache is updated.
+     */
+    private boolean maybeUpdateHeadlessSystemAppCache(@Nullable PackageInfo pkgInfo) {
         if (pkgInfo == null || pkgInfo.applicationInfo == null
                 || (!pkgInfo.applicationInfo.isSystemApp()
                         && !pkgInfo.applicationInfo.isUpdatedSystemApp())) {
             return false;
         }
+        final Intent frontDoorActivityIntent = new Intent(Intent.ACTION_MAIN)
+                .addCategory(Intent.CATEGORY_LAUNCHER)
+                .setPackage(pkgInfo.packageName);
+        List<ResolveInfo> res = mPackageManager.queryIntentActivitiesAsUser(frontDoorActivityIntent,
+                HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM);
+        return updateHeadlessSystemAppCache(pkgInfo.packageName, ArrayUtils.isEmpty(res));
+    }
+
+    private boolean updateHeadlessSystemAppCache(String packageName, boolean add) {
         synchronized (mHeadlessSystemApps) {
-            if (pkgInfo.activities == null || pkgInfo.activities.length == 0) {
-                // Headless system app.
-                return mHeadlessSystemApps.add(pkgInfo.packageName);
+            if (add) {
+                return mHeadlessSystemApps.add(packageName);
             } else {
-                return mHeadlessSystemApps.remove(pkgInfo.packageName);
+                return mHeadlessSystemApps.remove(packageName);
             }
         }
     }
@@ -1999,20 +2013,45 @@
         }
     }
 
+    /** Returns the packages that have launcher icons. */
+    private Set<String> getSystemPackagesWithLauncherActivities() {
+        final Intent intent = new Intent(Intent.ACTION_MAIN)
+                .addCategory(Intent.CATEGORY_LAUNCHER);
+        List<ResolveInfo> activities = mPackageManager.queryIntentActivitiesAsUser(intent,
+                HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM);
+        final ArraySet<String> ret = new ArraySet<>();
+        for (ResolveInfo ri : activities) {
+            ret.add(ri.activityInfo.packageName);
+        }
+        return ret;
+    }
+
     /** Call on system boot to get the initial set of headless system apps. */
     private void loadHeadlessSystemAppCache() {
-        Slog.d(TAG, "Loading headless system app cache. appIdleEnabled=" + mAppIdleEnabled);
+        final long start = SystemClock.uptimeMillis();
         final List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser(
                 HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM);
+
+        final Set<String> systemLauncherActivities = getSystemPackagesWithLauncherActivities();
+
         final int packageCount = packages.size();
         for (int i = 0; i < packageCount; i++) {
-            PackageInfo pkgInfo = packages.get(i);
-            if (pkgInfo != null && evaluateSystemAppException(pkgInfo)) {
+            final PackageInfo pkgInfo = packages.get(i);
+            if (pkgInfo == null) {
+                continue;
+            }
+            final String pkg = pkgInfo.packageName;
+            final boolean isHeadLess = !systemLauncherActivities.contains(pkg);
+
+            if (updateHeadlessSystemAppCache(pkg, isHeadLess)) {
                 mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE,
-                        UserHandle.USER_SYSTEM, -1, pkgInfo.packageName)
+                        UserHandle.USER_SYSTEM, -1, pkg)
                     .sendToTarget();
             }
         }
+        final long end = SystemClock.uptimeMillis();
+        Slog.d(TAG, "Loaded headless system app cache in " + (end - start) + " ms:"
+                + " appIdleEnabled=" + mAppIdleEnabled);
     }
 
     @Override
diff --git a/boot/hiddenapi/hiddenapi-max-target-o.txt b/boot/hiddenapi/hiddenapi-max-target-o.txt
index d3b5be9..3c16915 100644
--- a/boot/hiddenapi/hiddenapi-max-target-o.txt
+++ b/boot/hiddenapi/hiddenapi-max-target-o.txt
@@ -32472,14 +32472,6 @@
 Landroid/net/DhcpResults;->setServerAddress(Ljava/lang/String;)Z
 Landroid/net/DhcpResults;->setVendorInfo(Ljava/lang/String;)V
 Landroid/net/DhcpResults;->TAG:Ljava/lang/String;
-Landroid/net/EthernetManager;-><init>(Landroid/content/Context;Landroid/net/IEthernetManager;)V
-Landroid/net/EthernetManager;->mContext:Landroid/content/Context;
-Landroid/net/EthernetManager;->mHandler:Landroid/os/Handler;
-Landroid/net/EthernetManager;->mListeners:Ljava/util/ArrayList;
-Landroid/net/EthernetManager;->mService:Landroid/net/IEthernetManager;
-Landroid/net/EthernetManager;->mServiceListener:Landroid/net/IEthernetServiceListener$Stub;
-Landroid/net/EthernetManager;->MSG_AVAILABILITY_CHANGED:I
-Landroid/net/EthernetManager;->TAG:Ljava/lang/String;
 Landroid/net/EventLogTags;-><init>()V
 Landroid/net/EventLogTags;->NTP_FAILURE:I
 Landroid/net/EventLogTags;->NTP_SUCCESS:I
@@ -32513,39 +32505,6 @@
 Landroid/net/http/X509TrustManagerExtensions;->mDelegate:Lcom/android/org/conscrypt/TrustManagerImpl;
 Landroid/net/http/X509TrustManagerExtensions;->mIsSameTrustConfiguration:Ljava/lang/reflect/Method;
 Landroid/net/http/X509TrustManagerExtensions;->mTrustManager:Ljavax/net/ssl/X509TrustManager;
-Landroid/net/IEthernetManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/IEthernetManager$Stub$Proxy;->addListener(Landroid/net/IEthernetServiceListener;)V
-Landroid/net/IEthernetManager$Stub$Proxy;->getAvailableInterfaces()[Ljava/lang/String;
-Landroid/net/IEthernetManager$Stub$Proxy;->getConfiguration(Ljava/lang/String;)Landroid/net/IpConfiguration;
-Landroid/net/IEthernetManager$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
-Landroid/net/IEthernetManager$Stub$Proxy;->isAvailable(Ljava/lang/String;)Z
-Landroid/net/IEthernetManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/IEthernetManager$Stub$Proxy;->removeListener(Landroid/net/IEthernetServiceListener;)V
-Landroid/net/IEthernetManager$Stub$Proxy;->setConfiguration(Ljava/lang/String;Landroid/net/IpConfiguration;)V
-Landroid/net/IEthernetManager$Stub;-><init>()V
-Landroid/net/IEthernetManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IEthernetManager;
-Landroid/net/IEthernetManager$Stub;->DESCRIPTOR:Ljava/lang/String;
-Landroid/net/IEthernetManager$Stub;->TRANSACTION_addListener:I
-Landroid/net/IEthernetManager$Stub;->TRANSACTION_getAvailableInterfaces:I
-Landroid/net/IEthernetManager$Stub;->TRANSACTION_getConfiguration:I
-Landroid/net/IEthernetManager$Stub;->TRANSACTION_isAvailable:I
-Landroid/net/IEthernetManager$Stub;->TRANSACTION_removeListener:I
-Landroid/net/IEthernetManager$Stub;->TRANSACTION_setConfiguration:I
-Landroid/net/IEthernetManager;->addListener(Landroid/net/IEthernetServiceListener;)V
-Landroid/net/IEthernetManager;->getAvailableInterfaces()[Ljava/lang/String;
-Landroid/net/IEthernetManager;->getConfiguration(Ljava/lang/String;)Landroid/net/IpConfiguration;
-Landroid/net/IEthernetManager;->isAvailable(Ljava/lang/String;)Z
-Landroid/net/IEthernetManager;->removeListener(Landroid/net/IEthernetServiceListener;)V
-Landroid/net/IEthernetManager;->setConfiguration(Ljava/lang/String;Landroid/net/IpConfiguration;)V
-Landroid/net/IEthernetServiceListener$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/IEthernetServiceListener$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
-Landroid/net/IEthernetServiceListener$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/IEthernetServiceListener$Stub$Proxy;->onAvailabilityChanged(Ljava/lang/String;Z)V
-Landroid/net/IEthernetServiceListener$Stub;-><init>()V
-Landroid/net/IEthernetServiceListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IEthernetServiceListener;
-Landroid/net/IEthernetServiceListener$Stub;->DESCRIPTOR:Ljava/lang/String;
-Landroid/net/IEthernetServiceListener$Stub;->TRANSACTION_onAvailabilityChanged:I
-Landroid/net/IEthernetServiceListener;->onAvailabilityChanged(Ljava/lang/String;Z)V
 Landroid/net/IIpConnectivityMetrics$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/IIpConnectivityMetrics$Stub$Proxy;->addNetdEventCallback(ILandroid/net/INetdEventCallback;)Z
 Landroid/net/IIpConnectivityMetrics$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
diff --git a/core/api/current.txt b/core/api/current.txt
index c80c4cb..1391408a 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -142,7 +142,7 @@
     field @Deprecated public static final String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
     field public static final String READ_LOGS = "android.permission.READ_LOGS";
     field public static final String READ_MEDIA_AUDIO = "android.permission.READ_MEDIA_AUDIO";
-    field public static final String READ_MEDIA_IMAGE = "android.permission.READ_MEDIA_IMAGE";
+    field public static final String READ_MEDIA_IMAGES = "android.permission.READ_MEDIA_IMAGES";
     field public static final String READ_MEDIA_VIDEO = "android.permission.READ_MEDIA_VIDEO";
     field public static final String READ_NEARBY_STREAMING_POLICY = "android.permission.READ_NEARBY_STREAMING_POLICY";
     field public static final String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
@@ -18820,6 +18820,7 @@
     method public void onStartInput(android.view.inputmethod.EditorInfo, boolean);
     method public void onStartInputView(android.view.inputmethod.EditorInfo, boolean);
     method public boolean onStartStylusHandwriting();
+    method public void onStylusHandwritingMotionEvent(@NonNull android.view.MotionEvent);
     method public void onUnbindInput();
     method @Deprecated public void onUpdateCursor(android.graphics.Rect);
     method public void onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo);
@@ -26087,7 +26088,7 @@
     method @NonNull public java.util.List<android.media.tv.interactive.TvInteractiveAppInfo> getTvInteractiveAppServiceList();
     method public void prepare(@NonNull String, int);
     method public void registerAppLinkInfo(@NonNull String, @NonNull android.media.tv.interactive.AppLinkInfo);
-    method public void registerCallback(@NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback, @NonNull java.util.concurrent.Executor);
+    method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback);
     method public void sendAppLinkCommand(@NonNull String, @NonNull android.os.Bundle);
     method public void unregisterAppLinkInfo(@NonNull String, @NonNull android.media.tv.interactive.AppLinkInfo);
     method public void unregisterCallback(@NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback);
@@ -26157,10 +26158,10 @@
 
   public abstract static class TvInteractiveAppService.Session implements android.view.KeyEvent.Callback {
     ctor public TvInteractiveAppService.Session(@NonNull android.content.Context);
-    method public void layoutSurface(int, int, int, int);
-    method public final void notifyBiInteractiveAppCreated(@NonNull android.net.Uri, @Nullable String);
-    method public void notifySessionStateChanged(int, int);
-    method public final void notifyTeletextAppStateChanged(int);
+    method @CallSuper public void layoutSurface(int, int, int, int);
+    method @CallSuper public final void notifyBiInteractiveAppCreated(@NonNull android.net.Uri, @Nullable String);
+    method @CallSuper public void notifySessionStateChanged(int, int);
+    method @CallSuper public final void notifyTeletextAppStateChanged(int);
     method public void onAdResponse(@NonNull android.media.tv.AdResponse);
     method public void onBroadcastInfoResponse(@NonNull android.media.tv.BroadcastInfoResponse);
     method public void onContentAllowed();
@@ -26194,17 +26195,17 @@
     method public void onTuned(@NonNull android.net.Uri);
     method public void onVideoAvailable();
     method public void onVideoUnavailable(int);
-    method public void removeBroadcastInfo(int);
-    method public void requestAd(@NonNull android.media.tv.AdRequest);
-    method public void requestBroadcastInfo(@NonNull android.media.tv.BroadcastInfoRequest);
-    method public void requestCurrentChannelLcn();
-    method public void requestCurrentChannelUri();
-    method public void requestCurrentTvInputId();
-    method public void requestStreamVolume();
-    method public void requestTrackInfoList();
-    method public void sendPlaybackCommandRequest(@NonNull String, @Nullable android.os.Bundle);
-    method public void setMediaViewEnabled(boolean);
-    method public void setVideoBounds(@NonNull android.graphics.Rect);
+    method @CallSuper public void removeBroadcastInfo(int);
+    method @CallSuper public void requestAd(@NonNull android.media.tv.AdRequest);
+    method @CallSuper public void requestBroadcastInfo(@NonNull android.media.tv.BroadcastInfoRequest);
+    method @CallSuper public void requestCurrentChannelLcn();
+    method @CallSuper public void requestCurrentChannelUri();
+    method @CallSuper public void requestCurrentTvInputId();
+    method @CallSuper public void requestStreamVolume();
+    method @CallSuper public void requestTrackInfoList();
+    method @CallSuper public void sendPlaybackCommandRequest(@NonNull String, @Nullable android.os.Bundle);
+    method @CallSuper public void setMediaViewEnabled(boolean);
+    method @CallSuper public void setVideoBounds(@NonNull android.graphics.Rect);
   }
 
   public class TvInteractiveAppView extends android.view.ViewGroup {
@@ -26507,14 +26508,6 @@
     method public int getUid();
   }
 
-  public final class EthernetNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
-    ctor public EthernetNetworkSpecifier(@NonNull String);
-    method public int describeContents();
-    method @Nullable public String getInterfaceName();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkSpecifier> CREATOR;
-  }
-
   public final class Ikev2VpnProfile extends android.net.PlatformVpnProfile {
     method @NonNull public java.util.List<java.lang.String> getAllowedAlgorithms();
     method public int getMaxMtu();
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 7aef9a6..a32ebe4 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -232,22 +232,6 @@
 
 package android.net {
 
-  public class EthernetManager {
-    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void addInterfaceStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.InterfaceStateListener);
-    method public void removeInterfaceStateListener(@NonNull android.net.EthernetManager.InterfaceStateListener);
-    method public void setIncludeTestInterfaces(boolean);
-    field public static final int ROLE_CLIENT = 1; // 0x1
-    field public static final int ROLE_NONE = 0; // 0x0
-    field public static final int ROLE_SERVER = 2; // 0x2
-    field public static final int STATE_ABSENT = 0; // 0x0
-    field public static final int STATE_LINK_DOWN = 1; // 0x1
-    field public static final int STATE_LINK_UP = 2; // 0x2
-  }
-
-  public static interface EthernetManager.InterfaceStateListener {
-    method public void onInterfaceStateChanged(@NonNull String, int, int, @Nullable android.net.IpConfiguration);
-  }
-
   public class LocalSocket implements java.io.Closeable {
     ctor public LocalSocket(@NonNull java.io.FileDescriptor);
   }
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 5f2dcb3..09d1114 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -34,6 +34,7 @@
     field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
     field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
     field public static final String ALLOW_PLACE_IN_MULTI_PANE_SETTINGS = "android.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS";
+    field public static final String ALLOW_SLIPPERY_TOUCHES = "android.permission.ALLOW_SLIPPERY_TOUCHES";
     field public static final String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER";
     field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
     field public static final String ASSOCIATE_COMPANION_DEVICES = "android.permission.ASSOCIATE_COMPANION_DEVICES";
@@ -1700,20 +1701,22 @@
     method @NonNull public String getTitle();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.cloudsearch.SearchResult> CREATOR;
+    field public static final String EXTRAINFO_ACTION_APP_CARD = "android.app.cloudsearch.ACTION_APP_CARD";
     field public static final String EXTRAINFO_ACTION_BUTTON_IMAGE_PREREGISTERING = "android.app.cloudsearch.ACTION_BUTTON_IMAGE";
     field public static final String EXTRAINFO_ACTION_BUTTON_TEXT_PREREGISTERING = "android.app.cloudsearch.ACTION_BUTTON_TEXT";
+    field public static final String EXTRAINFO_ACTION_INSTALL_BUTTON = "android.app.cloudsearch.ACTION_INSTALL_BUTTON";
     field public static final String EXTRAINFO_APP_BADGES = "android.app.cloudsearch.APP_BADGES";
-    field public static final String EXTRAINFO_APP_CARD_ACTION = "android.app.cloudsearch.APP_CARD_ACTION";
     field public static final String EXTRAINFO_APP_CONTAINS_ADS_DISCLAIMER = "android.app.cloudsearch.APP_CONTAINS_ADS_DISCLAIMER";
     field public static final String EXTRAINFO_APP_CONTAINS_IAP_DISCLAIMER = "android.app.cloudsearch.APP_CONTAINS_IAP_DISCLAIMER";
     field public static final String EXTRAINFO_APP_DEVELOPER_NAME = "android.app.cloudsearch.APP_DEVELOPER_NAME";
     field public static final String EXTRAINFO_APP_DOMAIN_URL = "android.app.cloudsearch.APP_DOMAIN_URL";
     field public static final String EXTRAINFO_APP_IARC = "android.app.cloudsearch.APP_IARC";
     field public static final String EXTRAINFO_APP_ICON = "android.app.cloudsearch.APP_ICON";
+    field public static final String EXTRAINFO_APP_INSTALL_COUNT = "android.app.cloudsearch.APP_INSTALL_COUNT";
+    field public static final String EXTRAINFO_APP_PACKAGE_NAME = "android.app.cloudsearch.APP_PACKAGE_NAME";
     field public static final String EXTRAINFO_APP_REVIEW_COUNT = "android.app.cloudsearch.APP_REVIEW_COUNT";
     field public static final String EXTRAINFO_APP_SIZE_BYTES = "android.app.cloudsearch.APP_SIZE_BYTES";
     field public static final String EXTRAINFO_APP_STAR_RATING = "android.app.cloudsearch.APP_STAR_RATING";
-    field public static final String EXTRAINFO_INSTALL_BUTTON_ACTION = "android.app.cloudsearch.INSTALL_BUTTON_ACTION";
     field public static final String EXTRAINFO_LONG_DESCRIPTION = "android.app.cloudsearch.LONG_DESCRIPTION";
     field public static final String EXTRAINFO_SCREENSHOTS = "android.app.cloudsearch.SCREENSHOTS";
     field public static final String EXTRAINFO_SHORT_DESCRIPTION = "android.app.cloudsearch.SHORT_DESCRIPTION";
@@ -8523,45 +8526,6 @@
 
 package android.net {
 
-  public class EthernetManager {
-    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void connectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
-    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void disconnectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
-    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
-    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void updateConfiguration(@NonNull String, @NonNull android.net.EthernetNetworkUpdateRequest, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
-  }
-
-  public static interface EthernetManager.TetheredInterfaceCallback {
-    method public void onAvailable(@NonNull String);
-    method public void onUnavailable();
-  }
-
-  public static class EthernetManager.TetheredInterfaceRequest {
-    method public void release();
-  }
-
-  public final class EthernetNetworkManagementException extends java.lang.RuntimeException implements android.os.Parcelable {
-    ctor public EthernetNetworkManagementException(@NonNull String);
-    method public int describeContents();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkManagementException> CREATOR;
-  }
-
-  public final class EthernetNetworkUpdateRequest implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public android.net.IpConfiguration getIpConfiguration();
-    method @Nullable public android.net.NetworkCapabilities getNetworkCapabilities();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkUpdateRequest> CREATOR;
-  }
-
-  public static final class EthernetNetworkUpdateRequest.Builder {
-    ctor public EthernetNetworkUpdateRequest.Builder();
-    ctor public EthernetNetworkUpdateRequest.Builder(@NonNull android.net.EthernetNetworkUpdateRequest);
-    method @NonNull public android.net.EthernetNetworkUpdateRequest build();
-    method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setIpConfiguration(@NonNull android.net.IpConfiguration);
-    method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
-  }
-
   public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
     ctor public MatchAllNetworkSpecifier();
     method public int describeContents();
@@ -9032,7 +8996,7 @@
     method public void enableVerboseLogging(boolean);
     method @NonNull public int[] getChannelsMhzForBand(int);
     method @Nullable public android.net.wifi.nl80211.DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String);
-    method public int getMaxNumScanSsids(@NonNull String);
+    method public int getMaxSsidsPerScan(@NonNull String);
     method @NonNull public java.util.List<android.net.wifi.nl80211.NativeScanResult> getScanResults(@NonNull String, int);
     method @Nullable public android.net.wifi.nl80211.WifiNl80211Manager.TxPacketCounters getTxPacketCounters(@NonNull String);
     method public void notifyCountryCodeChanged(@Nullable String);
@@ -10334,6 +10298,7 @@
     field public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
     field public static final String NAMESPACE_NETD_NATIVE = "netd_native";
     field public static final String NAMESPACE_NNAPI_NATIVE = "nnapi_native";
+    field public static final String NAMESPACE_ON_DEVICE_PERSONALIZATION = "on_device_personalization";
     field public static final String NAMESPACE_OTA = "ota";
     field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service";
     field public static final String NAMESPACE_PERMISSIONS = "permissions";
@@ -13376,7 +13341,7 @@
   }
 
   public class TelephonyManager {
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
     method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
@@ -13476,7 +13441,8 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
     method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot();
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerCarrierPrivilegesCallback(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>);
@@ -13526,6 +13492,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterCarrierPrivilegesCallback(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
     method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
     method public void updateServiceLocation();
     field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
@@ -13631,8 +13598,13 @@
     field public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
-  public static interface TelephonyManager.CarrierPrivilegesListener {
-    method public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
+  public static interface TelephonyManager.CarrierPrivilegesCallback {
+    method public void onCarrierPrivilegesChanged(@NonNull java.util.Set<java.lang.String>, @NonNull java.util.Set<java.lang.Integer>);
+    method public default void onCarrierServiceChanged(@Nullable String, int);
+  }
+
+  @Deprecated public static interface TelephonyManager.CarrierPrivilegesListener {
+    method @Deprecated public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
   }
 
   public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b1a4e41..3d0ed20 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -868,6 +868,7 @@
         String processName;
         @UnsupportedAppUsage
         ApplicationInfo appInfo;
+        String sdkSandboxClientAppPackage;
         @UnsupportedAppUsage
         List<ProviderInfo> providers;
         ComponentName instrumentationName;
@@ -1113,9 +1114,9 @@
 
         @Override
         public final void bindApplication(String processName, ApplicationInfo appInfo,
-                ProviderInfoList providerList, ComponentName instrumentationName,
-                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
-                IInstrumentationWatcher instrumentationWatcher,
+                String sdkSandboxClientAppPackage, ProviderInfoList providerList,
+                ComponentName instrumentationName, ProfilerInfo profilerInfo,
+                Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
                 IUiAutomationConnection instrumentationUiConnection, int debugMode,
                 boolean enableBinderTracking, boolean trackAllocation,
                 boolean isRestrictedBackupMode, boolean persistent, Configuration config,
@@ -1155,6 +1156,7 @@
             AppBindData data = new AppBindData();
             data.processName = processName;
             data.appInfo = appInfo;
+            data.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage;
             data.providers = providerList.getList();
             data.instrumentationName = instrumentationName;
             data.instrumentationArgs = instrumentationArgs;
@@ -6536,6 +6538,9 @@
         }
 
         data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
+        if (data.sdkSandboxClientAppPackage != null) {
+            data.info.setSdkSandboxStorage(data.sdkSandboxClientAppPackage);
+        }
 
         if (agent != null) {
             handleAttachAgent(agent, data.info);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 7c7c7ef..4829dc0 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2367,7 +2367,7 @@
             null, // no permission for OP_WRITE_MEDIA_AUDIO
             Manifest.permission.READ_MEDIA_VIDEO,
             null, // no permission for OP_WRITE_MEDIA_VIDEO
-            Manifest.permission.READ_MEDIA_IMAGE,
+            Manifest.permission.READ_MEDIA_IMAGES,
             null, // no permission for OP_WRITE_MEDIA_IMAGES
             null, // no permission for OP_LEGACY_STORAGE
             null, // no permission for OP_ACCESS_ACCESSIBILITY
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index a3dd705a..f5eb1f6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1998,7 +1998,7 @@
     private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
             String instanceName, Handler handler, Executor executor, UserHandle user) {
         // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser and
-        // ActivityManagerLocal.bindSupplementalProcessService
+        // ActivityManagerLocal.bindSdkSandboxService
         IServiceConnection sd;
         if (conn == null) {
             throw new IllegalArgumentException("connection is null");
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 77657d5..f4fbcce 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -72,6 +72,7 @@
     @UnsupportedAppUsage
     void scheduleStopService(IBinder token);
     void bindApplication(in String packageName, in ApplicationInfo info,
+            in String sdkSandboxClientAppPackage,
             in ProviderInfoList providerList, in ComponentName testName,
             in ProfilerInfo profilerInfo, in Bundle testArguments,
             IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index d35c5be..deefea8 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -37,6 +37,7 @@
 import android.content.res.Resources;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.FileUtils;
 import android.os.GraphicsEnvironment;
 import android.os.Handler;
@@ -411,6 +412,26 @@
         }
     }
 
+    /** @hide */
+    void setSdkSandboxStorage(String sdkSandboxClientAppPackage) {
+        int userId = UserHandle.myUserId();
+        mDeviceProtectedDataDirFile = Environment
+                .getDataMiscDeSharedSdkSandboxDirectory(userId, sdkSandboxClientAppPackage)
+                .getAbsoluteFile();
+        mCredentialProtectedDataDirFile = Environment
+                .getDataMiscCeSharedSdkSandboxDirectory(userId, sdkSandboxClientAppPackage)
+                .getAbsoluteFile();
+
+        if ((mApplicationInfo.privateFlags
+                & ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0
+                && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
+            mDataDirFile = mDeviceProtectedDataDirFile;
+        } else {
+            mDataDirFile = mCredentialProtectedDataDirFile;
+        }
+        mDataDir = mDataDirFile.getAbsolutePath();
+    }
+
     public static void makePaths(ActivityThread activityThread,
                                  ApplicationInfo aInfo,
                                  List<String> outZipPaths) {
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index c6e36a3..89854bb 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -844,6 +844,24 @@
     }
 
     /**
+     * Sets an active {@link android.service.quicksettings.TileService} to listening state
+     *
+     * The {@code componentName}'s package must match the calling package.
+     *
+     * @param componentName the tile to set into listening state
+     * @see android.service.quicksettings.TileService#requestListeningState
+     * @hide
+     */
+    public void requestTileServiceListeningState(@NonNull ComponentName componentName) {
+        Objects.requireNonNull(componentName);
+        try {
+            getService().requestTileServiceListeningState(componentName, mContext.getUserId());
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Request to the user to add a {@link android.service.quicksettings.TileService}
      * to the set of current QS tiles.
      * <p>
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 58db93c..bf6f634 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -138,8 +138,6 @@
 import android.nearby.NearbyFrameworkInitializer;
 import android.net.ConnectivityFrameworkInitializer;
 import android.net.ConnectivityFrameworkInitializerTiramisu;
-import android.net.EthernetManager;
-import android.net.IEthernetManager;
 import android.net.INetworkPolicyManager;
 import android.net.IPacProxyManager;
 import android.net.IVpnManager;
@@ -789,15 +787,6 @@
                 return new LowpanManager(ctx.getOuterContext(), service);
             }});
 
-        registerService(Context.ETHERNET_SERVICE, EthernetManager.class,
-                new CachedServiceFetcher<EthernetManager>() {
-            @Override
-            public EthernetManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getServiceOrThrow(Context.ETHERNET_SERVICE);
-                IEthernetManager service = IEthernetManager.Stub.asInterface(b);
-                return new EthernetManager(ctx.getOuterContext(), service);
-            }});
-
         registerService(Context.WIFI_NL80211_SERVICE, WifiNl80211Manager.class,
                 new CachedServiceFetcher<WifiNl80211Manager>() {
                     @Override
diff --git a/core/java/android/app/cloudsearch/SearchResult.java b/core/java/android/app/cloudsearch/SearchResult.java
index 1ca01d4..c6583b6 100644
--- a/core/java/android/app/cloudsearch/SearchResult.java
+++ b/core/java/android/app/cloudsearch/SearchResult.java
@@ -71,8 +71,10 @@
             EXTRAINFO_APP_BADGES,
             EXTRAINFO_ACTION_BUTTON_TEXT_PREREGISTERING,
             EXTRAINFO_ACTION_BUTTON_IMAGE_PREREGISTERING,
-            EXTRAINFO_APP_CARD_ACTION,
-            EXTRAINFO_INSTALL_BUTTON_ACTION,
+            EXTRAINFO_ACTION_APP_CARD,
+            EXTRAINFO_ACTION_INSTALL_BUTTON,
+            EXTRAINFO_APP_PACKAGE_NAME,
+            EXTRAINFO_APP_INSTALL_COUNT,
             EXTRAINFO_WEB_URL,
             EXTRAINFO_WEB_ICON})
     public @interface SearchResultExtraInfoKey {}
@@ -123,12 +125,18 @@
             "android.app.cloudsearch.ACTION_BUTTON_IMAGE";
     /** Intent for tapping the app card, PendingIntent expected. */
     @SuppressLint("IntentName")
-    public static final String EXTRAINFO_APP_CARD_ACTION =
-            "android.app.cloudsearch.APP_CARD_ACTION";
+    public static final String EXTRAINFO_ACTION_APP_CARD =
+            "android.app.cloudsearch.ACTION_APP_CARD";
     /** Intent for tapping the install button, PendingIntent expected. */
     @SuppressLint("IntentName")
-    public static final String EXTRAINFO_INSTALL_BUTTON_ACTION =
-            "android.app.cloudsearch.INSTALL_BUTTON_ACTION";
+    public static final String EXTRAINFO_ACTION_INSTALL_BUTTON =
+            "android.app.cloudsearch.ACTION_INSTALL_BUTTON";
+    /** App's package name, String value expected. */
+    public static final String EXTRAINFO_APP_PACKAGE_NAME =
+            "android.app.cloudsearch.APP_PACKAGE_NAME";
+    /** App's install count, double value expected. */
+    public static final String EXTRAINFO_APP_INSTALL_COUNT =
+            "android.app.cloudsearch.APP_INSTALL_COUNT";
     /** Web content's URL, String value expected. */
     public static final String EXTRAINFO_WEB_URL = "android.app.cloudsearch.WEB_URL";
     /** Web content's domain icon, android.graphics.drawable.Icon expected. */
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index 3f5c5d2..d94b0d8 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -312,7 +312,7 @@
      * @hide
      */
     public static boolean areExactMatch(Signature[] a, Signature[] b) {
-        return (a.length == b.length) && ArrayUtils.containsAll(a, b)
+        return (ArrayUtils.size(a) == ArrayUtils.size(b)) && ArrayUtils.containsAll(a, b)
                 && ArrayUtils.containsAll(b, a);
     }
 
@@ -387,4 +387,4 @@
 
         return sPrime;
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
index 8b86a16..a65b681 100644
--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
@@ -379,6 +379,30 @@
     }
 
     /**
+     * Computes the maxSdkVersion. If the package is not compatible with this platform, populates
+     * {@code outError[0]} with an error message.
+     * <p>
+     * {@code maxVers} is compared against {@code platformSdkVersion}. If {@code maxVers} is less
+     * than the {@code platformSdkVersion} then populates {@code outError[0]} with an error message.
+     * Otherwise, it returns {@code maxVers} unmodified.
+     *
+     * @param maxVers maxSdkVersion number, if specified in the application manifest, or {@code
+     *                Integer.MAX_VALUE} otherwise
+     * @param platformSdkVersion   platform SDK version number, typically Build.VERSION.SDK_INT
+     * @return the maxSdkVersion that was recognised or an error if the condition is not satisfied
+     */
+    public static ParseResult<Integer> computeMaxSdkVersion(@IntRange(from = 0) int maxVers,
+            @IntRange(from = 1) int platformSdkVersion, @NonNull ParseInput input) {
+        if (platformSdkVersion > maxVers) {
+            return input.error(PackageManager.INSTALL_FAILED_NEWER_SDK,
+                    "Requires max SDK version " + maxVers + " but is "
+                            + platformSdkVersion);
+        } else {
+            return input.success(maxVers);
+        }
+    }
+
+    /**
      * Matches a given {@code targetCode} against a set of release codeNames. Target codes can
      * either be of the form {@code [codename]}" (e.g {@code "Q"}) or of the form {@code
      * [codename].[fingerprint]} (e.g {@code "Q.cafebc561"}).
diff --git a/core/java/android/inputmethodservice/InkWindow.java b/core/java/android/inputmethodservice/InkWindow.java
index 499634a..8289c26 100644
--- a/core/java/android/inputmethodservice/InkWindow.java
+++ b/core/java/android/inputmethodservice/InkWindow.java
@@ -27,6 +27,8 @@
 import android.os.IBinder;
 import android.util.Slog;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 
 import com.android.internal.policy.PhoneWindow;
@@ -40,6 +42,9 @@
 
     private final WindowManager mWindowManager;
     private boolean mIsViewAdded;
+    private View mInkView;
+    private InkVisibilityListener mInkViewVisibilityListener;
+    private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener;
 
     public InkWindow(@NonNull Context context) {
         super(context);
@@ -102,4 +107,77 @@
         lp.token = token;
         setAttributes(lp);
     }
+
+    @Override
+    public void addContentView(View view, ViewGroup.LayoutParams params) {
+        if (mInkView == null) {
+            mInkView = view;
+        } else if (mInkView != view) {
+            throw new IllegalStateException("Only one Child Inking view is permitted.");
+        }
+        super.addContentView(view, params);
+        initInkViewVisibilityListener();
+    }
+
+    @Override
+    public void setContentView(View view, ViewGroup.LayoutParams params) {
+        mInkView = view;
+        super.setContentView(view, params);
+        initInkViewVisibilityListener();
+    }
+
+    @Override
+    public void setContentView(View view) {
+        mInkView = view;
+        super.setContentView(view);
+        initInkViewVisibilityListener();
+    }
+
+    @Override
+    public void clearContentView() {
+        if (mGlobalLayoutListener != null && mInkView != null) {
+            mInkView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener);
+        }
+        mGlobalLayoutListener = null;
+        mInkView = null;
+        super.clearContentView();
+    }
+
+    /**
+    * Listener used by InkWindow to time the dispatching of {@link MotionEvent}s to Ink view, once
+    * it is visible to user.
+    */
+    interface InkVisibilityListener {
+        void onInkViewVisible();
+    }
+
+    void setInkViewVisibilityListener(InkVisibilityListener listener) {
+        mInkViewVisibilityListener = listener;
+        initInkViewVisibilityListener();
+    }
+
+    void initInkViewVisibilityListener() {
+        if (mInkView == null || mInkViewVisibilityListener == null
+                || mGlobalLayoutListener != null) {
+            return;
+        }
+        mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
+            @Override
+            public void onGlobalLayout() {
+                if (mInkView.isVisibleToUser()) {
+                    if (mInkViewVisibilityListener != null) {
+                        mInkViewVisibilityListener.onInkViewVisible();
+                    }
+                    mInkView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                    mGlobalLayoutListener = null;
+                }
+            }
+        };
+        mInkView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
+    }
+
+    boolean isInkViewVisible() {
+        return getDecorView().getVisibility() == View.VISIBLE
+                && mInkView != null && mInkView.isVisibleToUser();
+    }
 }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 656aea1..b46bb32 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -143,6 +143,7 @@
 import com.android.internal.inputmethod.InputMethodNavButtonFlags;
 import com.android.internal.inputmethod.InputMethodPrivilegedOperations;
 import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
+import com.android.internal.util.RingBuffer;
 import com.android.internal.view.IInlineSuggestionsRequestCallback;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.InlineSuggestionsRequestInfo;
@@ -334,6 +335,17 @@
             "persist.sys.ime.can_render_gestural_nav_buttons";
 
     /**
+     * Number of {@link MotionEvent} to buffer if IME is not ready with Ink view.
+     * This number may be configured eventually based on device's touch sampling frequency.
+     */
+    private static final int MAX_EVENTS_BUFFER = 500;
+
+    /**
+     * A circular buffer of size MAX_EVENTS_BUFFER in case IME is taking too long to add ink view.
+     **/
+    private RingBuffer<MotionEvent> mPendingEvents;
+
+    /**
      * Returns whether {@link InputMethodService} is responsible for rendering the back button and
      * the IME switcher button or not when the gestural navigation is enabled.
      *
@@ -954,7 +966,8 @@
             mInkWindow.show();
 
             // deliver previous @param stylusEvents
-            stylusEvents.forEach(mInkWindow.getDecorView()::dispatchTouchEvent);
+            stylusEvents.forEach(InputMethodService.this::onStylusHandwritingMotionEvent);
+
             // create receiver for channel
             mHandwritingEventReceiver = new SimpleBatchedInputEventReceiver(
                     channel,
@@ -963,11 +976,11 @@
                         if (!(event instanceof MotionEvent)) {
                             return false;
                         }
-                        return mInkWindow.getDecorView().dispatchTouchEvent((MotionEvent) event);
+                        onStylusHandwritingMotionEvent((MotionEvent) event);
+                        return true;
                     });
         }
 
-
         /**
          * {@inheritDoc}
          * @hide
@@ -2357,7 +2370,8 @@
      *
      * If the IME supports handwriting for the current input, it should return {@code true},
      * ensure its inking views are attached to the {@link #getStylusHandwritingWindow()}, and handle
-     * stylus input received on the ink window via {@link #getCurrentInputConnection()}.
+     * stylus input received from {@link #onStylusHandwritingMotionEvent(MotionEvent)} on the
+     * {@link #getStylusHandwritingWindow()} via {@link #getCurrentInputConnection()}.
      * @return {@code true} if IME can honor the request, {@code false} if IME cannot at this time.
      */
     public boolean onStartStylusHandwriting() {
@@ -2366,6 +2380,33 @@
     }
 
     /**
+     * Called after {@link #onStartStylusHandwriting()} returns {@code true} for every Stylus
+     * {@link MotionEvent}.
+     * By default, this method forwards all {@link MotionEvent}s to the
+     * {@link #getStylusHandwritingWindow()} once its visible, however IME can override it to
+     * receive them sooner.
+     * @param motionEvent {@link MotionEvent} from stylus.
+     */
+    public void onStylusHandwritingMotionEvent(@NonNull MotionEvent motionEvent) {
+        if (mInkWindow.isInkViewVisible()) {
+            mInkWindow.getDecorView().dispatchTouchEvent(motionEvent);
+        } else {
+            if (mPendingEvents == null) {
+                mPendingEvents = new RingBuffer(MotionEvent.class, MAX_EVENTS_BUFFER);
+            }
+            mPendingEvents.append(motionEvent);
+            mInkWindow.setInkViewVisibilityListener(() -> {
+                if (mPendingEvents != null && !mPendingEvents.isEmpty()) {
+                    for (MotionEvent event : mPendingEvents.toArray()) {
+                        mInkWindow.getDecorView().dispatchTouchEvent(event);
+                    }
+                    mPendingEvents.clear();
+                }
+            });
+        }
+    }
+
+    /**
      * Called when the current stylus handwriting session was finished (either by the system or
      * via {@link #finishStylusHandwriting()}.
      *
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index de1dc80..5f9fdbf 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -5655,6 +5655,7 @@
                         .setMaxStatsAgeMs(0)
                         .includePowerModels()
                         .includeProcessStateData()
+                        .includeVirtualUids()
                         .build());
         stats.dump(pw, prefix);
 
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
index 37bd51b..b3f4d98 100644
--- a/core/java/android/os/BatteryUsageStatsQuery.java
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -42,6 +42,7 @@
             FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL,
             FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY,
             FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA,
+            FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface BatteryUsageStatsFlags {}
@@ -69,6 +70,8 @@
 
     public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA = 0x0008;
 
+    public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS = 0x0010;
+
     private static final long DEFAULT_MAX_STATS_AGE_MS = 5 * 60 * 1000;
 
     private final int mFlags;
@@ -271,6 +274,15 @@
         }
 
         /**
+         * Requests to return attribution data for virtual UIDs such as
+         * {@link Process#SDK_SANDBOX_VIRTUAL_UID}.
+         */
+        public Builder includeVirtualUids() {
+            mFlags |= BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS;
+            return this;
+        }
+
+        /**
          * Requests to aggregate stored snapshots between the two supplied timestamps
          * @param fromTimestamp Exclusive starting timestamp, as per System.currentTimeMillis()
          * @param toTimestamp Inclusive ending timestamp, as per System.currentTimeMillis()
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 0a7a407..ecdc803 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -478,10 +478,20 @@
     }
 
     /** {@hide} */
+    public static File getDataMiscCeSharedSdkSandboxDirectory(int userId, String packageName) {
+        return buildPath(getDataMiscCeDirectory(userId), "sdksandbox", packageName, "shared");
+    }
+
+    /** {@hide} */
     public static File getDataMiscDeDirectory(int userId) {
         return buildPath(getDataDirectory(), "misc_de", String.valueOf(userId));
     }
 
+    /** {@hide} */
+    public static File getDataMiscDeSharedSdkSandboxDirectory(int userId, String packageName) {
+        return buildPath(getDataMiscDeDirectory(userId), "sdksandbox", packageName, "shared");
+    }
+
     private static File getDataProfilesDeDirectory(int userId) {
         return buildPath(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId));
     }
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index a1ff923..77d1498 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -202,20 +202,24 @@
         private static final String PACKAGE_NAME_UNINITIALIZED = "";
         private final BatteryStats.Uid mBatteryStatsUid;
         private final int mUid;
+        private final boolean mIsVirtualUid;
         private String mPackageWithHighestDrain = PACKAGE_NAME_UNINITIALIZED;
         private boolean mExcludeFromBatteryUsageStats;
 
         public Builder(BatteryConsumerData data, @NonNull BatteryStats.Uid batteryStatsUid) {
-            super(data, CONSUMER_TYPE_UID);
-            mBatteryStatsUid = batteryStatsUid;
-            mUid = batteryStatsUid.getUid();
-            data.putLong(COLUMN_INDEX_UID, mUid);
+            this(data, batteryStatsUid, batteryStatsUid.getUid());
         }
 
         public Builder(BatteryConsumerData data, int uid) {
+            this(data, null, uid);
+        }
+
+        private Builder(BatteryConsumerData data, @Nullable BatteryStats.Uid batteryStatsUid,
+                int uid) {
             super(data, CONSUMER_TYPE_UID);
-            mBatteryStatsUid = null;
+            mBatteryStatsUid = batteryStatsUid;
             mUid = uid;
+            mIsVirtualUid = mUid == Process.SDK_SANDBOX_VIRTUAL_UID;
             data.putLong(COLUMN_INDEX_UID, mUid);
         }
 
@@ -232,6 +236,10 @@
             return mUid;
         }
 
+        public boolean isVirtualUid() {
+            return mIsVirtualUid;
+        }
+
         /**
          * Sets the name of the package owned by this UID that consumed the highest amount
          * of power since BatteryStats reset.
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 052e4d0..6982b3a 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -322,6 +322,13 @@
     public static final String NAMESPACE_NNAPI_NATIVE = "nnapi_native";
 
     /**
+     * Namespace for all OnDevicePersonalization related feature.
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_ON_DEVICE_PERSONALIZATION = "on_device_personalization";
+
+    /**
      * Namespace for features related to the Package Manager Service.
      *
      * @hide
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index b507328..0829d28 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -15,18 +15,19 @@
  */
 package android.service.quicksettings;
 
-import android.Manifest;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.app.Dialog;
 import android.app.Service;
+import android.app.StatusBarManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.drawable.Icon;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -147,13 +148,6 @@
             "android.service.quicksettings.TOGGLEABLE_TILE";
 
     /**
-     * Used to notify SysUI that Listening has be requested.
-     * @hide
-     */
-    public static final String ACTION_REQUEST_LISTENING =
-            "android.service.quicksettings.action.REQUEST_LISTENING";
-
-    /**
      * @hide
      */
     public static final String EXTRA_SERVICE = "service";
@@ -482,14 +476,24 @@
      *
      * This method is only applicable to tiles that have {@link #META_DATA_ACTIVE_TILE} defined
      * as true on their TileService Manifest declaration, and will do nothing otherwise.
+     *
+     * For apps targeting {@link Build.VERSION_CODES#TIRAMISU} or later, this call may throw
+     * the following exceptions if the request is not valid:
+     * <ul>
+     *     <li> {@link NullPointerException} if {@code component} is {@code null}.</li>
+     *     <li> {@link SecurityException} if the package of {@code component} does not match
+     *     the calling package or if the calling user cannot act on behalf of the user from the
+     *     {@code context}.</li>
+     *     <li> {@link IllegalArgumentException} if the user of the {@code context} is not the
+     *     current user.</li>
+     * </ul>
      */
     public static final void requestListeningState(Context context, ComponentName component) {
-        final ComponentName sysuiComponent = ComponentName.unflattenFromString(
-                context.getResources().getString(
-                        com.android.internal.R.string.config_systemUIServiceComponent));
-        Intent intent = new Intent(ACTION_REQUEST_LISTENING);
-        intent.putExtra(Intent.EXTRA_COMPONENT_NAME, component);
-        intent.setPackage(sysuiComponent.getPackageName());
-        context.sendBroadcast(intent, Manifest.permission.BIND_QUICK_SETTINGS_TILE);
+        StatusBarManager sbm = context.getSystemService(StatusBarManager.class);
+        if (sbm == null) {
+            Log.e(TAG, "No StatusBarManager service found");
+            return;
+        }
+        sbm.requestTileServiceListeningState(component);
     }
 }
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index c1fcd66..f844592 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -27,6 +27,7 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.service.carrier.CarrierService;
 import android.telephony.Annotation.CallState;
 import android.telephony.Annotation.DataActivityType;
 import android.telephony.Annotation.DisconnectCauses;
@@ -36,6 +37,7 @@
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SimActivationState;
 import android.telephony.Annotation.SrvccState;
+import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
 import android.telephony.TelephonyManager.CarrierPrivilegesListener;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
@@ -44,17 +46,19 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.listeners.ListenerExecutor;
-import com.android.internal.telephony.ICarrierPrivilegesListener;
+import com.android.internal.telephony.ICarrierPrivilegesCallback;
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 import com.android.internal.telephony.ITelephonyRegistry;
 
 import java.lang.ref.WeakReference;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
 
 /**
  * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update
@@ -1260,34 +1264,78 @@
                 pkgName, attributionTag, callback, new int[0], notifyNow);
     }
 
-    private static class CarrierPrivilegesListenerWrapper extends ICarrierPrivilegesListener.Stub
+    // TODO(b/216549778): Remove listener logic once all clients switch to CarrierPrivilegesCallback
+    private static class CarrierPrivilegesCallbackWrapper extends ICarrierPrivilegesCallback.Stub
             implements ListenerExecutor {
-        private final WeakReference<CarrierPrivilegesListener> mListener;
-        private final Executor mExecutor;
+        // Either mListener or mCallback may be null, never both
+        @Nullable private final WeakReference<CarrierPrivilegesListener> mListener;
+        @Nullable private final WeakReference<CarrierPrivilegesCallback> mCallback;
+        @NonNull private final Executor mExecutor;
 
-        CarrierPrivilegesListenerWrapper(CarrierPrivilegesListener listener, Executor executor) {
+        CarrierPrivilegesCallbackWrapper(
+                @NonNull CarrierPrivilegesCallback callback, @NonNull Executor executor) {
+            mListener = null;
+            mCallback = new WeakReference<>(callback);
+            mExecutor = executor;
+        }
+
+        CarrierPrivilegesCallbackWrapper(
+                @NonNull CarrierPrivilegesListener listener, @NonNull Executor executor) {
             mListener = new WeakReference<>(listener);
+            mCallback = null;
             mExecutor = executor;
         }
 
         @Override
         public void onCarrierPrivilegesChanged(
-                List<String> privilegedPackageNames, int[] privilegedUids) {
-            Binder.withCleanCallingIdentity(
-                    () ->
-                            executeSafely(
-                                    mExecutor,
-                                    mListener::get,
-                                    cpl ->
-                                            cpl.onCarrierPrivilegesChanged(
-                                                    privilegedPackageNames, privilegedUids)));
+                @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) {
+            if (mListener != null) {
+                Binder.withCleanCallingIdentity(
+                        () ->
+                                executeSafely(
+                                        mExecutor,
+                                        mListener::get,
+                                        cpl ->
+                                                cpl.onCarrierPrivilegesChanged(
+                                                        privilegedPackageNames, privilegedUids)));
+            }
+
+            if (mCallback != null) {
+                // AIDL interface does not support Set, keep the List/Array and translate them here
+                Set<String> privilegedPkgNamesSet = Set.copyOf(privilegedPackageNames);
+                Set<Integer> privilegedUidsSet = Arrays.stream(privilegedUids).boxed().collect(
+                        Collectors.toSet());
+                Binder.withCleanCallingIdentity(
+                        () ->
+                                executeSafely(
+                                        mExecutor,
+                                        mCallback::get,
+                                        cpc ->
+                                                cpc.onCarrierPrivilegesChanged(
+                                                        privilegedPkgNamesSet, privilegedUidsSet)));
+            }
+        }
+
+        @Override
+        public void onCarrierServiceChanged(@Nullable String packageName, int uid) {
+            if (mCallback != null) {
+                Binder.withCleanCallingIdentity(
+                        () ->
+                                executeSafely(
+                                        mExecutor,
+                                        mCallback::get,
+                                        cpc -> cpc.onCarrierServiceChanged(packageName, uid)));
+            }
         }
     }
 
-    @GuardedBy("sCarrierPrivilegeListeners")
-    private static final WeakHashMap<
-                    CarrierPrivilegesListener, WeakReference<CarrierPrivilegesListenerWrapper>>
-            sCarrierPrivilegeListeners = new WeakHashMap<>();
+    // TODO(b/216549778): Change the map key to CarrierPrivilegesCallback once all clients switch to
+    // CarrierPrivilegesCallback. Before that, the key is either CarrierPrivilegesCallback or
+    // CarrierPrivilegesListener, no logic actually depends on the type.
+    @NonNull
+    @GuardedBy("sCarrierPrivilegeCallbacks")
+    private static final WeakHashMap<Object,  WeakReference<CarrierPrivilegesCallbackWrapper>>
+            sCarrierPrivilegeCallbacks = new WeakHashMap<>();
 
     /**
      * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
@@ -1297,7 +1345,11 @@
      * @param logicalSlotIndex The SIM slot to listen on
      * @param executor The executor where {@code listener} will be invoked
      * @param listener The callback to register
+     *
+     * @deprecated Use {@link #addCarrierPrivilegesCallback} instead. This API will be removed
+     * prior to API finalization.
      */
+    @Deprecated
     public void addCarrierPrivilegesListener(
             int logicalSlotIndex,
             @NonNull @CallbackExecutor Executor executor,
@@ -1305,18 +1357,18 @@
         if (listener == null || executor == null) {
             throw new IllegalArgumentException("listener and executor must be non-null");
         }
-        synchronized (sCarrierPrivilegeListeners) {
-            WeakReference<CarrierPrivilegesListenerWrapper> existing =
-                    sCarrierPrivilegeListeners.get(listener);
+        synchronized (sCarrierPrivilegeCallbacks) {
+            WeakReference<CarrierPrivilegesCallbackWrapper> existing =
+                    sCarrierPrivilegeCallbacks.get(listener);
             if (existing != null && existing.get() != null) {
                 Log.d(TAG, "addCarrierPrivilegesListener: listener already registered");
                 return;
             }
-            CarrierPrivilegesListenerWrapper wrapper =
-                    new CarrierPrivilegesListenerWrapper(listener, executor);
-            sCarrierPrivilegeListeners.put(listener, new WeakReference<>(wrapper));
+            CarrierPrivilegesCallbackWrapper wrapper =
+                    new CarrierPrivilegesCallbackWrapper(listener, executor);
+            sCarrierPrivilegeCallbacks.put(listener, new WeakReference<>(wrapper));
             try {
-                sRegistry.addCarrierPrivilegesListener(
+                sRegistry.addCarrierPrivilegesCallback(
                         logicalSlotIndex,
                         wrapper,
                         mContext.getOpPackageName(),
@@ -1331,19 +1383,84 @@
      * Unregisters a {@link CarrierPrivilegesListener}.
      *
      * @param listener The callback to unregister
+     *
+     * @deprecated Use {@link #removeCarrierPrivilegesCallback} instead. The callback will prior
+     * to API finalization.
      */
+    @Deprecated
     public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
         if (listener == null) {
             throw new IllegalArgumentException("listener must be non-null");
         }
-        synchronized (sCarrierPrivilegeListeners) {
-            WeakReference<CarrierPrivilegesListenerWrapper> ref =
-                    sCarrierPrivilegeListeners.remove(listener);
+        synchronized (sCarrierPrivilegeCallbacks) {
+            WeakReference<CarrierPrivilegesCallbackWrapper> ref =
+                    sCarrierPrivilegeCallbacks.remove(listener);
             if (ref == null) return;
-            CarrierPrivilegesListenerWrapper wrapper = ref.get();
+            CarrierPrivilegesCallbackWrapper wrapper = ref.get();
             if (wrapper == null) return;
             try {
-                sRegistry.removeCarrierPrivilegesListener(wrapper, mContext.getOpPackageName());
+                sRegistry.removeCarrierPrivilegesCallback(wrapper, mContext.getOpPackageName());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to
+     * receive callbacks when the set of packages with carrier privileges changes. The callback will
+     * immediately be called with the latest state.
+     *
+     * @param logicalSlotIndex The SIM slot to listen on
+     * @param executor The executor where {@code listener} will be invoked
+     * @param callback The callback to register
+     */
+    public void addCarrierPrivilegesCallback(
+            int logicalSlotIndex,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull CarrierPrivilegesCallback callback) {
+        if (callback == null || executor == null) {
+            throw new IllegalArgumentException("callback and executor must be non-null");
+        }
+        synchronized (sCarrierPrivilegeCallbacks) {
+            WeakReference<CarrierPrivilegesCallbackWrapper> existing =
+                    sCarrierPrivilegeCallbacks.get(callback);
+            if (existing != null && existing.get() != null) {
+                Log.d(TAG, "addCarrierPrivilegesCallback: callback already registered");
+                return;
+            }
+            CarrierPrivilegesCallbackWrapper wrapper =
+                    new CarrierPrivilegesCallbackWrapper(callback, executor);
+            sCarrierPrivilegeCallbacks.put(callback, new WeakReference<>(wrapper));
+            try {
+                sRegistry.addCarrierPrivilegesCallback(
+                        logicalSlotIndex,
+                        wrapper,
+                        mContext.getOpPackageName(),
+                        mContext.getAttributionTag());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Unregisters a {@link CarrierPrivilegesCallback}.
+     *
+     * @param callback The callback to unregister
+     */
+    public void removeCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("listener must be non-null");
+        }
+        synchronized (sCarrierPrivilegeCallbacks) {
+            WeakReference<CarrierPrivilegesCallbackWrapper> ref =
+                    sCarrierPrivilegeCallbacks.remove(callback);
+            if (ref == null) return;
+            CarrierPrivilegesCallbackWrapper wrapper = ref.get();
+            if (wrapper == null) return;
+            try {
+                sRegistry.removeCarrierPrivilegesCallback(wrapper, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -1359,15 +1476,33 @@
      */
     public void notifyCarrierPrivilegesChanged(
             int logicalSlotIndex,
-            @NonNull List<String> privilegedPackageNames,
-            @NonNull int[] privilegedUids) {
+            @NonNull Set<String> privilegedPackageNames,
+            @NonNull Set<Integer> privilegedUids) {
         if (privilegedPackageNames == null || privilegedUids == null) {
             throw new IllegalArgumentException(
                     "privilegedPackageNames and privilegedUids must be non-null");
         }
         try {
-            sRegistry.notifyCarrierPrivilegesChanged(
-                    logicalSlotIndex, privilegedPackageNames, privilegedUids);
+            // AIDL doesn't support Set yet. Convert Set to List/Array
+            List<String> pkgList = List.copyOf(privilegedPackageNames);
+            int[] uids = privilegedUids.stream().mapToInt(Number::intValue).toArray();
+            sRegistry.notifyCarrierPrivilegesChanged(logicalSlotIndex, pkgList, uids);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Notify listeners that the {@link CarrierService} for current user has changed.
+     *
+     * @param logicalSlotIndex the SIM slot the change occurred on
+     * @param packageName the package name of the changed {@link CarrierService}
+     * @param uid the UID of the changed {@link CarrierService}
+     */
+    public void notifyCarrierServiceChanged(int logicalSlotIndex, @Nullable String packageName,
+            int uid) {
+        try {
+            sRegistry.notifyCarrierServiceChanged(logicalSlotIndex, packageName, uid);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 18e65c9..e79bdce 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -873,6 +873,7 @@
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
         mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
         mFallbackEventHandler = new PhoneFallbackEventHandler(context);
+        // TODO(b/222696368): remove getSfInstance usage and use vsyncId for transactions
         mChoreographer = useSfChoreographer
                 ? Choreographer.getSfInstance() : Choreographer.getInstance();
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
@@ -1777,6 +1778,7 @@
         updateInternalDisplay(displayId, mView.getResources());
         mImeFocusController.onMovedToDisplay();
         mAttachInfo.mDisplayState = mDisplay.getState();
+        mDisplayInstallOrientation = mDisplay.getInstallOrientation();
         // Internal state updated, now notify the view hierarchy.
         mView.dispatchMovedToDisplay(mDisplay, config);
     }
@@ -3448,6 +3450,12 @@
                     mReportNextDraw = false;
                     pendingDrawFinished();
                 }
+
+                // Make sure the consumer is not waiting if the view root was just made invisible.
+                if (mBLASTDrawConsumer != null) {
+                    mBLASTDrawConsumer.accept(null);
+                    mBLASTDrawConsumer = null;
+                }
             }
         }
 
diff --git a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
index 45555bf..dbbe4b9 100644
--- a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
+++ b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
@@ -24,6 +24,7 @@
  *
  * @hide
  */
+// TODO(b/222698397): remove getSfInstance/this class usage and use vsyncId for transactions
 public final class SfVsyncFrameCallbackProvider implements AnimationFrameCallbackProvider {
 
     private final Choreographer mChoreographer;
diff --git a/core/java/com/android/internal/os/AudioPowerCalculator.java b/core/java/com/android/internal/os/AudioPowerCalculator.java
index f9310b0..ebf0ca2 100644
--- a/core/java/com/android/internal/os/AudioPowerCalculator.java
+++ b/core/java/com/android/internal/os/AudioPowerCalculator.java
@@ -78,7 +78,9 @@
         final double powerMah = mPowerEstimator.calculatePower(durationMs);
         app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_AUDIO, durationMs)
                 .setConsumedPower(BatteryConsumer.POWER_COMPONENT_AUDIO, powerMah);
-        total.durationMs += durationMs;
-        total.powerMah += powerMah;
+        if (!app.isVirtualUid()) {
+            total.durationMs += durationMs;
+            total.powerMah += powerMah;
+        }
     }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 70b9639..5253956 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -546,9 +546,9 @@
                 final LongArrayMultiStateCounter onBatteryScreenOffCounter =
                         u.getProcStateScreenOffTimeCounter().getCounter();
 
-                if (uid == parentUid) {
-                    mKernelSingleUidTimeReader.addDelta(uid, onBatteryCounter, timestampMs);
-                    mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter,
+                if (uid == parentUid || Process.isSdkSandboxUid(uid)) {
+                    mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryCounter, timestampMs);
+                    mKernelSingleUidTimeReader.addDelta(parentUid, onBatteryScreenOffCounter,
                             timestampMs);
                 } else {
                     Uid.ChildUid childUid = u.getChildUid(uid);
@@ -4560,7 +4560,10 @@
         mIsolatedUidRefCounts.put(uid, refCount + 1);
     }
 
-    public int mapUid(int uid) {
+    private int mapUid(int uid) {
+        if (Process.isSdkSandboxUid(uid)) {
+            return Process.getAppUidForSdkSandboxUid(uid);
+        }
         int isolated = mIsolatedUids.get(uid, -1);
         return isolated > 0 ? isolated : uid;
     }
@@ -4656,16 +4659,18 @@
             long elapsedRealtimeMs, long uptimeMs) {
         int parentUid = mapUid(uid);
         if (uid != parentUid) {
-            // Isolated UIDs process state is already rolled up into parent, so no need to track
-            // Otherwise the parent's process state will get downgraded incorrectly
-            return;
+            if (Process.isIsolated(uid)) {
+                // Isolated UIDs process state is already rolled up into parent, so no need to track
+                // Otherwise the parent's process state will get downgraded incorrectly
+                return;
+            }
         }
         // TODO(b/155216561): It is possible for isolated uids to be in a higher
         // state than its parent uid. We should track the highest state within the union of host
         // and isolated uids rather than only the parent uid.
         FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
                 ActivityManager.processStateAmToProto(state));
-        getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
+        getUidStatsLocked(parentUid, elapsedRealtimeMs, uptimeMs)
                 .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs);
     }
 
@@ -15970,6 +15975,9 @@
     public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) {
         Uid u = mUidStats.get(uid);
         if (u == null) {
+            if (Process.isSdkSandboxUid(uid)) {
+                Log.wtf(TAG, "Tracking an SDK Sandbox UID");
+            }
             u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs);
             mUidStats.put(uid, u);
         }
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index a1c1917..81c6ee7 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -22,6 +22,7 @@
 import android.os.BatteryUsageStats;
 import android.os.BatteryUsageStatsQuery;
 import android.os.Parcel;
+import android.os.Process;
 import android.os.SystemClock;
 import android.os.UidBatteryConsumer;
 import android.util.Log;
@@ -162,6 +163,8 @@
         final boolean includeProcessStateData = ((query.getFlags()
                 & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0)
                 && mStats.isProcessStateDataAvailable();
+        final boolean includeVirtualUids =  ((query.getFlags()
+                & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS) != 0);
 
         final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder(
                 mStats.getCustomEnergyConsumerNames(), includePowerModels,
@@ -174,6 +177,10 @@
         SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats();
         for (int i = uidStats.size() - 1; i >= 0; i--) {
             final BatteryStats.Uid uid = uidStats.valueAt(i);
+            if (!includeVirtualUids && uid.getUid() == Process.SDK_SANDBOX_VIRTUAL_UID) {
+                continue;
+            }
+
             batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(uid)
                     .setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND,
                             getProcessBackgroundTimeMs(uid, realtimeUs))
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 2ebf689..e52c8a3 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -139,8 +139,10 @@
                         BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerAndDuration.powerMah,
                         powerModel);
 
-        powerAndDuration.totalDurationMs += powerAndDuration.durationMs;
-        powerAndDuration.totalPowerMah += powerAndDuration.powerMah;
+        if (!app.isVirtualUid()) {
+            powerAndDuration.totalDurationMs += powerAndDuration.durationMs;
+            powerAndDuration.totalPowerMah += powerAndDuration.powerMah;
+        }
 
         if (query.isProcessStateDataNeeded() && powerAndDuration.keys != null) {
             for (int j = 0; j < powerAndDuration.keys.length; j++) {
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index 1fc2baf..8704e93 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -117,7 +117,9 @@
                 }
             }
             calculateApp(app, app.getBatteryStatsUid(), query, result, keys);
-            totalPowerMah += result.powerMah;
+            if (!app.isVirtualUid()) {
+                totalPowerMah += result.powerMah;
+            }
         }
 
         final long consumptionUC = batteryStats.getCpuMeasuredBatteryConsumptionUC();
diff --git a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java
index cbbb526..0853bd8 100644
--- a/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java
+++ b/core/java/com/android/internal/os/CustomMeasuredPowerCalculator.java
@@ -96,7 +96,9 @@
                 app.setConsumedPowerForCustomComponent(
                         BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + i,
                         customMeasuredPowerMah[i]);
-                newTotalPowerMah[i] += customMeasuredPowerMah[i];
+                if (!app.isVirtualUid()) {
+                    newTotalPowerMah[i] += customMeasuredPowerMah[i];
+                }
             }
         }
         return newTotalPowerMah;
diff --git a/core/java/com/android/internal/os/GnssPowerCalculator.java b/core/java/com/android/internal/os/GnssPowerCalculator.java
index 0f78306..070783a 100644
--- a/core/java/com/android/internal/os/GnssPowerCalculator.java
+++ b/core/java/com/android/internal/os/GnssPowerCalculator.java
@@ -58,8 +58,11 @@
             final long consumptionUC =
                     app.getBatteryStatsUid().getGnssMeasuredBatteryConsumptionUC();
             final int powerModel = getPowerModel(consumptionUC, query);
-            appsPowerMah += calculateApp(app, app.getBatteryStatsUid(), powerModel,
+            final double powerMah = calculateApp(app, app.getBatteryStatsUid(), powerModel,
                     rawRealtimeUs, averageGnssPowerMa, consumptionUC);
+            if (!app.isVirtualUid()) {
+                appsPowerMah += powerMah;
+            }
         }
 
         final long consumptionUC = batteryStats.getGnssMeasuredBatteryConsumptionUC();
diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
index f4624de..d0df45c 100644
--- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
+++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
@@ -136,12 +136,14 @@
             PowerAndDuration total,
             BatteryUsageStatsQuery query, BatteryConsumer.Key[] keys) {
         final long radioActiveDurationMs = calculateDuration(u, BatteryStats.STATS_SINCE_CHARGED);
-        total.totalAppDurationMs += radioActiveDurationMs;
-
         final long consumptionUC = u.getMobileRadioMeasuredBatteryConsumptionUC();
         final int powerModel = getPowerModel(consumptionUC, query);
         final double powerMah = calculatePower(u, powerModel, radioActiveDurationMs, consumptionUC);
-        total.totalAppPowerMah += powerMah;
+
+        if (!app.isVirtualUid()) {
+            total.totalAppDurationMs += radioActiveDurationMs;
+            total.totalAppPowerMah += powerMah;
+        }
 
         app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
                         radioActiveDurationMs)
diff --git a/core/java/com/android/internal/os/ScreenPowerCalculator.java b/core/java/com/android/internal/os/ScreenPowerCalculator.java
index 67d3d6e..5ca1a85 100644
--- a/core/java/com/android/internal/os/ScreenPowerCalculator.java
+++ b/core/java/com/android/internal/os/ScreenPowerCalculator.java
@@ -96,8 +96,10 @@
                                     appPowerAndDuration.durationMs)
                             .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN,
                                     appPowerAndDuration.powerMah, powerModel);
-                    totalAppPower += appPowerAndDuration.powerMah;
-                    totalAppDuration += appPowerAndDuration.durationMs;
+                    if (!app.isVirtualUid()) {
+                        totalAppPower += appPowerAndDuration.powerMah;
+                        totalAppDuration += appPowerAndDuration.durationMs;
+                    }
                 }
                 break;
             case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
@@ -192,10 +194,13 @@
         long totalActivityTimeMs = 0;
         final SparseLongArray activityTimeArray = new SparseLongArray();
         for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
-            final BatteryStats.Uid uid = uidBatteryConsumerBuilders.valueAt(i).getBatteryStatsUid();
+            final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
+            final BatteryStats.Uid uid = app.getBatteryStatsUid();
             final long timeMs = getProcessForegroundTimeMs(uid, rawRealtimeUs);
             activityTimeArray.put(uid.getUid(), timeMs);
-            totalActivityTimeMs += timeMs;
+            if (!app.isVirtualUid()) {
+                totalActivityTimeMs += timeMs;
+            }
         }
 
         if (totalActivityTimeMs >= MIN_ACTIVE_TIME_FOR_SMEARING) {
diff --git a/core/java/com/android/internal/os/SensorPowerCalculator.java b/core/java/com/android/internal/os/SensorPowerCalculator.java
index 4a9c91d..573692e 100644
--- a/core/java/com/android/internal/os/SensorPowerCalculator.java
+++ b/core/java/com/android/internal/os/SensorPowerCalculator.java
@@ -51,7 +51,9 @@
                 builder.getUidBatteryConsumerBuilders();
         for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
             final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
-            appsPowerMah += calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs);
+            if (!app.isVirtualUid()) {
+                appsPowerMah += calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs);
+            }
         }
 
         builder.getAggregateBatteryConsumerBuilder(
diff --git a/core/java/com/android/internal/os/UserPowerCalculator.java b/core/java/com/android/internal/os/UserPowerCalculator.java
index 22cff6e..79e3a19 100644
--- a/core/java/com/android/internal/os/UserPowerCalculator.java
+++ b/core/java/com/android/internal/os/UserPowerCalculator.java
@@ -49,7 +49,11 @@
                 builder.getUidBatteryConsumerBuilders();
 
         for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
-            UidBatteryConsumer.Builder uidBuilder = uidBatteryConsumerBuilders.valueAt(i);
+            final UidBatteryConsumer.Builder uidBuilder = uidBatteryConsumerBuilders.valueAt(i);
+            if (uidBuilder.isVirtualUid()) {
+                continue;
+            }
+
             final int uid = uidBuilder.getUid();
             if (UserHandle.getAppId(uid) < Process.FIRST_APPLICATION_UID) {
                 continue;
diff --git a/core/java/com/android/internal/os/VideoPowerCalculator.java b/core/java/com/android/internal/os/VideoPowerCalculator.java
index a222bcb..2daf15e 100644
--- a/core/java/com/android/internal/os/VideoPowerCalculator.java
+++ b/core/java/com/android/internal/os/VideoPowerCalculator.java
@@ -75,7 +75,9 @@
         final double powerMah = mPowerEstimator.calculatePower(durationMs);
         app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_VIDEO, durationMs)
                 .setConsumedPower(BatteryConsumer.POWER_COMPONENT_VIDEO, powerMah);
-        total.durationMs += durationMs;
-        total.powerMah += powerMah;
+        if (!app.isVirtualUid()) {
+            total.durationMs += durationMs;
+            total.powerMah += powerMah;
+        }
     }
 }
diff --git a/core/java/com/android/internal/os/WakelockPowerCalculator.java b/core/java/com/android/internal/os/WakelockPowerCalculator.java
index 0251e1c..3ae7113 100644
--- a/core/java/com/android/internal/os/WakelockPowerCalculator.java
+++ b/core/java/com/android/internal/os/WakelockPowerCalculator.java
@@ -62,8 +62,10 @@
                     BatteryStats.STATS_SINCE_CHARGED);
             app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WAKELOCK, result.durationMs)
                     .setConsumedPower(BatteryConsumer.POWER_COMPONENT_WAKELOCK, result.powerMah);
-            totalAppDurationMs += result.durationMs;
-            appPowerMah += result.powerMah;
+            if (!app.isVirtualUid()) {
+                totalAppDurationMs += result.durationMs;
+                appPowerMah += result.powerMah;
+            }
 
             if (app.getUid() == Process.ROOT_UID) {
                 osBatteryConsumer = app;
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 8c3fb86..2181821 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -111,9 +111,10 @@
             calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), powerModel,
                     rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED,
                     batteryStats.hasWifiActivityReporting(), consumptionUC);
-
-            totalAppDurationMs += powerDurationAndTraffic.durationMs;
-            totalAppPowerMah += powerDurationAndTraffic.powerMah;
+            if (!app.isVirtualUid()) {
+                totalAppDurationMs += powerDurationAndTraffic.durationMs;
+                totalAppPowerMah += powerDurationAndTraffic.powerMah;
+            }
 
             app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_WIFI,
                     powerDurationAndTraffic.durationMs);
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index d629d66..089179d 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -297,6 +297,11 @@
      */
     void runGcForTest();
 
+    /**
+     * Send a request to SystemUI to put a given active tile in listening state
+     */
+    void requestTileServiceListeningState(in ComponentName componentName);
+
     void requestAddTile(in ComponentName componentName, in CharSequence appName, in CharSequence label, in Icon icon, in IAddTileResultCallback callback);
     void cancelRequestAddTile(in String packageName);
 
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 1d60c50..2ee5e79 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -91,7 +91,7 @@
     void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed, boolean isBubbleSuppressed);
     void hideCurrentInputMethodForBubbles();
     void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
-    void clearInlineReplyUriPermissions(String key);
+    oneway void clearInlineReplyUriPermissions(String key);
     void onNotificationFeedbackReceived(String key, in Bundle feedback);
 
     void onGlobalActionsShown();
@@ -171,6 +171,11 @@
      */
     void suppressAmbientDisplay(boolean suppress);
 
+    /**
+     * Send a request to SystemUI to put a given active tile in listening state
+     */
+    void requestTileServiceListeningState(in ComponentName componentName, int userId);
+
     void requestAddTile(in ComponentName componentName, in CharSequence label, in Icon icon, int userId, in IAddTileResultCallback callback);
     void cancelRequestAddTile(in String packageName);
 
diff --git a/core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl b/core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl
similarity index 84%
rename from core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl
rename to core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl
index 6ca8cec..0c8e73f 100644
--- a/core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl
+++ b/core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl
@@ -16,7 +16,8 @@
 
 package com.android.internal.telephony;
 
-oneway interface ICarrierPrivilegesListener {
+oneway interface ICarrierPrivilegesCallback {
     void onCarrierPrivilegesChanged(
             in List<String> privilegedPackageNames, in int[] privilegedUids);
+    void onCarrierServiceChanged(in String carrierServicePackageName, in int carrierServiceUid);
 }
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 9712d7e..c7fa757 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -32,7 +32,7 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.emergency.EmergencyNumber;
-import com.android.internal.telephony.ICarrierPrivilegesListener;
+import com.android.internal.telephony.ICarrierPrivilegesCallback;
 import com.android.internal.telephony.IPhoneStateListener;
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 
@@ -102,9 +102,11 @@
     void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId,
             in List<LinkCapacityEstimate> linkCapacityEstimateList);
 
-    void addCarrierPrivilegesListener(
-            int phoneId, ICarrierPrivilegesListener callback, String pkg, String featureId);
-    void removeCarrierPrivilegesListener(ICarrierPrivilegesListener callback, String pkg);
+    void addCarrierPrivilegesCallback(
+            int phoneId, ICarrierPrivilegesCallback callback, String pkg, String featureId);
+    void removeCarrierPrivilegesCallback(ICarrierPrivilegesCallback callback, String pkg);
     void notifyCarrierPrivilegesChanged(
             int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids);
+    void notifyCarrierServiceChanged(int phoneId, in String packageName, int uid);
+
 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f835792..521b2f6 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1135,7 +1135,7 @@
     public List<ComponentName> getEnabledTrustAgents(int userId) {
         String serialized = getString(ENABLED_TRUST_AGENTS, userId);
         if (TextUtils.isEmpty(serialized)) {
-            return null;
+            return new ArrayList<ComponentName>();
         }
         String[] split = serialized.split(",");
         ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index eedf7fa..eba6cca 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -1567,6 +1567,7 @@
         REG_JNI(register_android_graphics_classes),
         REG_JNI(register_android_graphics_BLASTBufferQueue),
         REG_JNI(register_android_graphics_GraphicBuffer),
+        REG_JNI(register_android_graphics_GraphicsStatsService),
         REG_JNI(register_android_graphics_SurfaceTexture),
         REG_JNI(register_android_database_CursorWindow),
         REG_JNI(register_android_database_SQLiteConnection),
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index 0c05da5..679a4f0 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -34,6 +34,7 @@
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/system_properties.h>
 #include <vector>
 
 namespace android {
@@ -43,10 +44,10 @@
 using android::zygote::ZygoteFailure;
 
 // WARNING: Knows a little about the wire protocol used to communicate with Zygote.
-// TODO: Fix error handling.
 
+// Commands and nice names have large arbitrary size limits to avoid dynamic memory allocation.
 constexpr size_t MAX_COMMAND_BYTES = 32768;
-constexpr size_t NICE_NAME_BYTES = 50;
+constexpr size_t NICE_NAME_BYTES = 128;
 
 // A buffer optionally bundled with a file descriptor from which we can fill it.
 // Does not own the file descriptor; destroying a NativeCommandBuffer does not
@@ -190,6 +191,9 @@
         size_t copy_len = std::min(name_len, NICE_NAME_BYTES - 1);
         memcpy(mNiceName, arg_start + NN_LENGTH, copy_len);
         mNiceName[copy_len] = '\0';
+        if (haveWrapProperty()) {
+          return false;
+        }
         continue;
       }
       if (arg_end - arg_start == IW_LENGTH
@@ -222,6 +226,8 @@
         }
         saw_setgid = true;
       }
+      // ro.debuggable can be handled entirely in the child unless --invoke-with is also specified.
+      // Thus we do not need to check it here.
     }
     return saw_runtime_args && saw_setuid && saw_setgid;
   }
@@ -249,6 +255,14 @@
   }
 
  private:
+  bool haveWrapProperty() {
+    static const char* WRAP = "wrap.";
+    static const size_t WRAP_LENGTH = strlen(WRAP);
+    char propNameBuf[WRAP_LENGTH + NICE_NAME_BYTES];
+    strcpy(propNameBuf, WRAP);
+    strlcpy(propNameBuf + WRAP_LENGTH, mNiceName, NICE_NAME_BYTES);
+    return __system_property_find(propNameBuf) != nullptr;
+  }
   // Picky version of atoi(). No sign or unexpected characters allowed. Return -1 on failure.
   static int digitsVal(char* start, char* end) {
     int result = 0;
@@ -269,7 +283,7 @@
   uint32_t mNext;  // Index of first character past last line returned by readLine.
   int32_t mLinesLeft;  // Lines in current command that haven't yet been read.
   int mFd;  // Open file descriptor from which we can read more. -1 if none.
-  char mNiceName[NICE_NAME_BYTES];
+  char mNiceName[NICE_NAME_BYTES];  // Always null terminated.
   char mBuffer[MAX_COMMAND_BYTES];
 };
 
@@ -372,6 +386,7 @@
             jint minUid,
             jstring managed_nice_name) {
 
+  ALOGI("Entering forkRepeatedly native zygote loop");
   NativeCommandBuffer* n_buffer = reinterpret_cast<NativeCommandBuffer*>(j_buffer);
   int session_socket = n_buffer->getFd();
   std::vector<int> session_socket_fds {session_socket};
@@ -400,7 +415,8 @@
   socklen_t cred_size = sizeof credentials;
   if (getsockopt(n_buffer->getFd(), SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1
       || cred_size != sizeof credentials) {
-    fail_fn_1(CREATE_ERROR("ForkMany failed to get initial credentials, %s", strerror(errno)));
+    fail_fn_1(CREATE_ERROR("ForkRepeatedly failed to get initial credentials, %s",
+                           strerror(errno)));
   }
 
   bool first_time = true;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index becac7f..ddc37ee 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1030,10 +1030,10 @@
       targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S} or lower, this permission
       must not be used and the READ_EXTERNAL_STORAGE permission must be used instead.
      <p>Protection level: dangerous -->
-    <permission android:name="android.permission.READ_MEDIA_IMAGE"
+    <permission android:name="android.permission.READ_MEDIA_IMAGES"
                 android:permissionGroup="android.permission-group.UNDEFINED"
-                android:label="@string/permlab_readMediaImage"
-                android:description="@string/permdesc_readMediaImage"
+                android:label="@string/permlab_readMediaImages"
+                android:description="@string/permdesc_readMediaImages"
                 android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write to external storage.
@@ -6160,10 +6160,10 @@
     <!-- Allows input events to be monitored. Very dangerous!  @hide -->
     <permission android:name="android.permission.MONITOR_INPUT"
                 android:protectionLevel="signature|recents" />
-    <!-- Allows the use of FLAG_SLIPPERY, which permits touch events to slip from the current
-         window to the window where the touch currently is on top of.  @hide -->
+    <!-- @SystemApi Allows the use of FLAG_SLIPPERY, which permits touch events to slip from the
+         current window to the window where the touch currently is on top of.  @hide -->
     <permission android:name="android.permission.ALLOW_SLIPPERY_TOUCHES"
-                android:protectionLevel="signature|recents" />
+                android:protectionLevel="signature|privileged|recents|role" />
     <!--  Allows the caller to change the associations between input devices and displays.
         Very dangerous! @hide -->
     <permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0a572be..269aa1b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2723,7 +2723,7 @@
     <string name="config_bandwidthEstimateSource">bandwidth_estimator</string>
 
     <!-- Whether force to enable telephony new data stack or not -->
-    <bool name="config_force_enable_telephony_new_data_stack">true</bool>
+    <bool name="config_force_enable_telephony_new_data_stack">false</bool>
 
     <!-- Whether WiFi display is supported by this device.
          There are many prerequisites for this feature to work correctly.
@@ -2988,6 +2988,12 @@
 
     </string-array>
 
+    <!-- When migrating notification settings into the permission framework, whether all existing
+         apps should be marked as 'user-set' (true) or whether only the apps that have explicitly
+         modified notification settings should be marked as 'user-set' (false). Users will not see
+         system generated permission prompts for 'user-set' apps. -->
+    <bool name="config_notificationForceUserSetOnUpgrade">true</bool>
+
     <!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM -->
     <integer name="config_toastDefaultGravity">0x00000051</integer>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5de8fec..04a70cb 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1918,9 +1918,9 @@
     <string name="permdesc_readMediaVideo">Allows the app to read video files from your shared storage.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can read from. [CHAR LIMIT=none] -->
-    <string name="permlab_readMediaImage">read image files from shared storage</string>
+    <string name="permlab_readMediaImages">read image files from shared storage</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can read from. [CHAR LIMIT=none] -->
-    <string name="permdesc_readMediaImage">Allows the app to read image files from your shared storage.</string>
+    <string name="permdesc_readMediaImages">Allows the app to read image files from your shared storage.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can write to. [CHAR LIMIT=none] -->
     <string name="permlab_sdcardWrite">modify or delete the contents of your shared storage</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6f34b3f..1f0b22b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4770,5 +4770,6 @@
   <java-symbol type="integer" name="config_bg_current_drain_exempted_types" />
   <java-symbol type="bool" name="config_bg_current_drain_high_threshold_by_bg_location" />
   <java-symbol type="drawable" name="ic_swap_horiz" />
+  <java-symbol type="bool" name="config_notificationForceUserSetOnUpgrade" />
 
 </resources>
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 5c9044c..beadc446 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -424,6 +424,7 @@
 
         @Override
         public void bindApplication(String s, ApplicationInfo applicationInfo,
+                String sdkSandboxClientAppPackage,
                 ProviderInfoList list, ComponentName componentName, ProfilerInfo profilerInfo,
                 Bundle bundle, IInstrumentationWatcher iInstrumentationWatcher,
                 IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1,
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
index 0e394c1..bfb3449 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
@@ -30,6 +30,7 @@
 public class BatteryStatsSensorTest extends TestCase {
 
     private static final int UID = 10500;
+    private static final int UID_2 = 10501; // second uid for testing pool usage
     private static final int SENSOR_ID = -10000;
 
     @SmallTest
@@ -239,7 +240,6 @@
 
     @SmallTest
     public void testPooledBackgroundUsage() throws Exception {
-        final int UID_2 = 20000; // second uid for testing pool usage
         final MockClock clocks = new MockClock();
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
         bi.mForceOnBattery = true;
diff --git a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
index b659f37..940ca96 100644
--- a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
@@ -19,14 +19,20 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.UserInfo;
@@ -50,6 +56,7 @@
 import org.mockito.Mockito;
 
 import java.nio.charset.StandardCharsets;
+import java.util.List;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -164,6 +171,16 @@
         verify(ils).isWeakEscrowTokenValid(eq(testHandle), eq(testToken), eq(testUserId));
     }
 
+    @Test
+    public void testGetEnabledTrustAgentsNotNull() throws RemoteException {
+        int testUserId = 10;
+        ILockSettings ils = createTestLockSettings();
+        when(ils.getString(anyString(), any(), anyInt())).thenReturn("");
+        List<ComponentName> trustAgents = mLockPatternUtils.getEnabledTrustAgents(testUserId);
+        assertNotNull(trustAgents);
+        assertEquals(0, trustAgents.size());
+    }
+
     private ILockSettings createTestLockSettings() {
         final Context context = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
         mLockPatternUtils = spy(new LockPatternUtils(context));
diff --git a/data/etc/com.android.launcher3.xml b/data/etc/com.android.launcher3.xml
index 598d202..36a5134 100644
--- a/data/etc/com.android.launcher3.xml
+++ b/data/etc/com.android.launcher3.xml
@@ -16,6 +16,7 @@
   -->
 <permissions>
     <privapp-permissions package="com.android.launcher3">
+        <permission name="android.permission.ALLOW_SLIPPERY_TOUCHES"/>
         <permission name="android.permission.BIND_APPWIDGET"/>
         <permission name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"/>
         <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index ae350ec..d1873a0 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -17,6 +17,7 @@
 <permissions>
     <privapp-permissions package="com.android.systemui">
         <permission name="android.permission.CAPTURE_AUDIO_OUTPUT"/>
+        <permission name="android.permission.ALLOW_SLIPPERY_TOUCHES"/>
         <permission name="android.permission.BATTERY_STATS"/>
         <permission name="android.permission.BIND_APPWIDGET"/>
         <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 88920c8..a829339 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -241,7 +241,7 @@
     </split-permission>
     <split-permission name="android.permission.READ_EXTERNAL_STORAGE"
                       targetSdk="33">
-        <new-permission name="android.permission.READ_MEDIA_IMAGE" />
+        <new-permission name="android.permission.READ_MEDIA_IMAGES" />
     </split-permission>
     <split-permission name="android.permission.BLUETOOTH"
                       targetSdk="31">
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index ffaa4ea..c1addbf 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -1098,19 +1098,16 @@
         }
 
         // Draw the appropriate mask anchored to (0,0).
+        final int saveCount = mMaskCanvas.save();
         final int left = bounds.left;
         final int top = bounds.top;
-        if (mState.mRippleStyle == STYLE_SOLID) {
-            mMaskCanvas.translate(-left, -top);
-        }
+        mMaskCanvas.translate(-left, -top);
         if (maskType == MASK_EXPLICIT) {
             drawMask(mMaskCanvas);
         } else if (maskType == MASK_CONTENT) {
             drawContent(mMaskCanvas);
         }
-        if (mState.mRippleStyle == STYLE_SOLID) {
-            mMaskCanvas.translate(left, top);
-        }
+        mMaskCanvas.restoreToCount(saveCount);
         if (mState.mRippleStyle == STYLE_PATTERNED) {
             for (int i = 0; i < mRunningAnimations.size(); i++) {
                 mRunningAnimations.get(i).getProperties().getShader().setShader(mMaskShader);
@@ -1210,9 +1207,13 @@
         updateMaskShaderIfNeeded();
 
         // Position the shader to account for canvas translation.
-        if (mMaskShader != null && mState.mRippleStyle == STYLE_SOLID) {
+        if (mMaskShader != null) {
             final Rect bounds = getBounds();
-            mMaskMatrix.setTranslate(bounds.left - x, bounds.top - y);
+            if (mState.mRippleStyle == STYLE_PATTERNED) {
+                mMaskMatrix.setTranslate(bounds.left, bounds.top);
+            } else {
+                mMaskMatrix.setTranslate(bounds.left - x, bounds.top - y);
+            }
             mMaskShader.setLocalMatrix(mMaskMatrix);
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipInputConsumer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipInputConsumer.java
index e57abc2..0f3ff36 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipInputConsumer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipInputConsumer.java
@@ -148,6 +148,7 @@
         mMainExecutor.execute(() -> {
             // Choreographer.getSfInstance() must be called on the thread that the input event
             // receiver should be receiving events
+            // TODO(b/222697646): remove getSfInstance usage and use vsyncId for transactions
             mInputEventReceiver = new InputEventReceiver(inputChannel,
                 Looper.myLooper(), Choreographer.getSfInstance());
             if (mRegistrationListener != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
index f3789fd..fa0f092 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
@@ -95,6 +95,8 @@
                 final FrameCallbackScheduler scheduler = new FrameCallbackScheduler() {
                     @Override
                     public void postFrameCallback(@androidx.annotation.NonNull Runnable runnable) {
+                        // TODO(b/222697646): remove getSfInstance usage and use vsyncId for
+                        //  transactions
                         Choreographer.getSfInstance().postFrameCallback(t -> runnable.run());
                     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index c816f18..abf1a95 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -625,6 +625,7 @@
 
     class PipResizeInputEventReceiver extends BatchedInputEventReceiver {
         PipResizeInputEventReceiver(InputChannel channel, Looper looper) {
+            // TODO(b/222697646): remove getSfInstance usage and use vsyncId for transactions
             super(channel, looper, Choreographer.getSfInstance());
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
index 72b93480..d6dacd1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
@@ -30,17 +30,18 @@
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.util.ArraySet;
-import android.util.Log;
 import android.util.Size;
 import android.view.Gravity;
 
 import androidx.annotation.NonNull;
 
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.pip.PipSnapAlgorithm;
 import com.android.wm.shell.pip.tv.TvPipKeepClearAlgorithm.Placement;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.util.Set;
 
@@ -90,7 +91,10 @@
     /** Returns the destination bounds to place the PIP window on entry. */
     @Override
     public Rect getEntryDestinationBounds() {
-        if (DEBUG) Log.d(TAG, "getEntryDestinationBounds()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: getEntryDestinationBounds()", TAG);
+        }
         if (mTvPipBoundsState.isTvExpandedPipSupported()
                 && mTvPipBoundsState.getDesiredTvExpandedAspectRatio() != 0
                 && !mTvPipBoundsState.isTvPipManuallyCollapsed()) {
@@ -104,7 +108,10 @@
     /** Returns the current bounds adjusted to the new aspect ratio, if valid. */
     @Override
     public Rect getAdjustedDestinationBounds(Rect currentBounds, float newAspectRatio) {
-        if (DEBUG) Log.d(TAG, "getAdjustedDestinationBounds: " + newAspectRatio);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: getAdjustedDestinationBounds: %f", TAG, newAspectRatio);
+        }
         return getTvPipBounds().getBounds();
     }
 
@@ -122,7 +129,11 @@
         Set<Rect> unrestrictedKeepClearAreas = mTvPipBoundsState.getUnrestrictedKeepClearAreas();
 
         if (mTvPipBoundsState.isImeShowing()) {
-            if (DEBUG) Log.d(TAG, "IME showing, height: " + mTvPipBoundsState.getImeHeight());
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: IME showing, height: %d",
+                        TAG, mTvPipBoundsState.getImeHeight());
+            }
 
             final Rect imeBounds = new Rect(
                     0,
@@ -145,15 +156,22 @@
                 unrestrictedKeepClearAreas);
 
         if (DEBUG) {
-            Log.d(TAG, "pipSize: " + pipSize);
-            Log.d(TAG, "screenSize: " + screenSize);
-            Log.d(TAG, "stashOffset: " + mTvPipBoundsState.getStashOffset());
-            Log.d(TAG, "insetBounds: " + insetBounds.toShortString());
-            Log.d(TAG, "pipSize: " + pipSize);
-            Log.d(TAG, "gravity: " + Gravity.toString(mTvPipBoundsState.getTvPipGravity()));
-            Log.d(TAG, "restrictedKeepClearAreas: " + restrictedKeepClearAreas);
-            Log.d(TAG, "unrestrictedKeepClearAreas: " + unrestrictedKeepClearAreas);
-            Log.d(TAG, "placement: " + placement);
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: screenSize: %s", TAG, screenSize);
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: stashOffset: %d", TAG, mTvPipBoundsState.getStashOffset());
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: insetBounds: %s", TAG, insetBounds.toShortString());
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: pipSize: %s", TAG, pipSize);
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: gravity: %s", TAG, Gravity.toString(mTvPipBoundsState.getTvPipGravity()));
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: restrictedKeepClearAreas: %s", TAG, restrictedKeepClearAreas);
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: unrestrictedKeepClearAreas: %s", TAG, unrestrictedKeepClearAreas);
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: placement: %s", TAG, placement);
         }
 
         return placement;
@@ -164,9 +182,11 @@
      */
     int updateGravityOnExpandToggled(int previousGravity, boolean expanding) {
         if (DEBUG) {
-            Log.d(TAG, "updateGravityOnExpandToggled(), expanding: " + expanding
-                    + ", mOrientation: " + mTvPipBoundsState.getTvFixedPipOrientation()
-                    + ", previous gravity: " + Gravity.toString(previousGravity));
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: updateGravityOnExpandToggled(), expanding: %b"
+                    + ", mOrientation: %d, previous gravity: %s",
+                    TAG, expanding, mTvPipBoundsState.getTvFixedPipOrientation(),
+                    Gravity.toString(previousGravity));
         }
 
         if (!mTvPipBoundsState.isTvExpandedPipSupported()) {
@@ -218,7 +238,10 @@
             }
         }
         mTvPipBoundsState.setTvPipGravity(updatedGravity);
-        if (DEBUG) Log.d(TAG, "new gravity: " + Gravity.toString(updatedGravity));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: new gravity: %s", TAG, Gravity.toString(updatedGravity));
+        }
 
         return gravityToSave;
     }
@@ -227,7 +250,10 @@
      * @return true if gravity changed
      */
     boolean updateGravity(int keycode) {
-        if (DEBUG) Log.d(TAG, "updateGravity, keycode: " + keycode);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: updateGravity, keycode: %d", TAG, keycode);
+        }
 
         // Check if position change is valid
         if (mTvPipBoundsState.isTvPipExpanded()) {
@@ -284,7 +310,10 @@
 
         if (updatedGravity != currentGravity) {
             mTvPipBoundsState.setTvPipGravity(updatedGravity);
-            if (DEBUG) Log.d(TAG, "new gravity: " + Gravity.toString(updatedGravity));
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: new gravity: %s", TAG, Gravity.toString(updatedGravity));
+            }
             return true;
         }
         return false;
@@ -313,7 +342,9 @@
 
         final Size expandedSize;
         if (expandedRatio == 0) {
-            Log.d(TAG, "updateExpandedPipSize(): Expanded mode aspect ratio of 0 not supported");
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                       "%s: updateExpandedPipSize(): Expanded mode aspect ratio"
+                               + " of 0 not supported", TAG);
             return;
         } else if (expandedRatio < 1) {
             // vertical
@@ -324,10 +355,16 @@
                 float aspectRatioHeight = mFixedExpandedWidthInPx / expandedRatio;
 
                 if (maxHeight > aspectRatioHeight) {
-                    if (DEBUG) Log.d(TAG, "Accommodate aspect ratio");
+                    if (DEBUG) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: Accommodate aspect ratio", TAG);
+                    }
                     expandedSize = new Size(mFixedExpandedWidthInPx, (int) aspectRatioHeight);
                 } else {
-                    if (DEBUG) Log.d(TAG, "Aspect ratio is too extreme, use max size");
+                    if (DEBUG) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: Aspect ratio is too extreme, use max size", TAG);
+                    }
                     expandedSize = new Size(mFixedExpandedWidthInPx, maxHeight);
                 }
             }
@@ -339,10 +376,16 @@
                 int maxWidth = displayLayout.width() - (2 * mScreenEdgeInsets.x);
                 float aspectRatioWidth = mFixedExpandedHeightInPx * expandedRatio;
                 if (maxWidth > aspectRatioWidth) {
-                    if (DEBUG) Log.d(TAG, "Accommodate aspect ratio");
+                    if (DEBUG) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: Accommodate aspect ratio", TAG);
+                    }
                     expandedSize = new Size((int) aspectRatioWidth, mFixedExpandedHeightInPx);
                 } else {
-                    if (DEBUG) Log.d(TAG, "Aspect ratio is too extreme, use max size");
+                    if (DEBUG) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: Aspect ratio is too extreme, use max size", TAG);
+                    }
                     expandedSize = new Size(maxWidth, mFixedExpandedHeightInPx);
                 }
             }
@@ -350,8 +393,9 @@
 
         mTvPipBoundsState.setTvExpandedSize(expandedSize);
         if (DEBUG) {
-            Log.d(TAG, "updateExpandedPipSize(): expanded size, width=" + expandedSize.getWidth()
-                    + ", height=" + expandedSize.getHeight());
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                       "%s: updateExpandedPipSize(): expanded size, width: %d, height: %d",
+                    TAG, expandedSize.getWidth(), expandedSize.getHeight());
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index 03c5e98..f397ac0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -32,9 +32,9 @@
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.util.Log;
 import android.view.Gravity;
 
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.R;
 import com.android.wm.shell.WindowManagerShellWrapper;
 import com.android.wm.shell.common.DisplayController;
@@ -50,6 +50,7 @@
 import com.android.wm.shell.pip.PipTaskOrganizer;
 import com.android.wm.shell.pip.PipTransitionController;
 import com.android.wm.shell.pip.tv.TvPipKeepClearAlgorithm.Placement;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -182,10 +183,16 @@
     }
 
     private void onConfigurationChanged(Configuration newConfig) {
-        if (DEBUG) Log.d(TAG, "onConfigurationChanged(), state=" + stateToName(mState));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onConfigurationChanged(), state=%s", TAG, stateToName(mState));
+        }
 
         if (isPipShown()) {
-            if (DEBUG) Log.d(TAG, "  > closing Pip.");
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s:  > closing Pip.", TAG);
+            }
             closePip();
         }
 
@@ -208,10 +215,16 @@
      */
     @Override
     public void showPictureInPictureMenu() {
-        if (DEBUG) Log.d(TAG, "showPictureInPictureMenu(), state=" + stateToName(mState));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: showPictureInPictureMenu(), state=%s", TAG, stateToName(mState));
+        }
 
         if (mState == STATE_NO_PIP) {
-            if (DEBUG) Log.d(TAG, "  > cannot open Menu from the current state.");
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s:  > cannot open Menu from the current state.", TAG);
+            }
             return;
         }
 
@@ -221,7 +234,10 @@
 
     @Override
     public void closeMenu() {
-        if (DEBUG) Log.d(TAG, "closeMenu(), state before=" + stateToName(mState));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: closeMenu(), state before=%s", TAG, stateToName(mState));
+        }
         setState(STATE_PIP);
         mTvPipBoundsAlgorithm.keepUnstashedForCurrentKeepClearAreas();
         updatePinnedStackBounds();
@@ -237,7 +253,10 @@
      */
     @Override
     public void movePipToFullscreen() {
-        if (DEBUG) Log.d(TAG, "movePipToFullscreen(), state=" + stateToName(mState));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: movePipToFullscreen(), state=%s", TAG, stateToName(mState));
+        }
 
         mPipTaskOrganizer.exitPip(mResizeAnimationDuration, false /* requestEnterSplit */);
         onPipDisappeared();
@@ -245,7 +264,10 @@
 
     @Override
     public void togglePipExpansion() {
-        if (DEBUG) Log.d(TAG, "togglePipExpansion()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: togglePipExpansion()", TAG);
+        }
         boolean expanding = !mTvPipBoundsState.isTvPipExpanded();
         int saveGravity = mTvPipBoundsAlgorithm
                 .updateGravityOnExpandToggled(mPreviousGravity, expanding);
@@ -264,7 +286,10 @@
             mPreviousGravity = Gravity.NO_GRAVITY;
             updatePinnedStackBounds();
         } else {
-            if (DEBUG) Log.d(TAG, "Position hasn't changed");
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: Position hasn't changed", TAG);
+            }
         }
     }
 
@@ -323,10 +348,16 @@
 
     /** Animates the PiP to the given bounds. */
     private void movePinnedStackTo(Rect bounds) {
-        if (DEBUG) Log.d(TAG, "movePinnedStackTo() - new pip bounds: " + bounds.toShortString());
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: movePinnedStack() - new pip bounds: %s", TAG, bounds.toShortString());
+        }
         mPipTaskOrganizer.scheduleAnimateResizePip(bounds,
                 mResizeAnimationDuration, rect -> {
-                    if (DEBUG) Log.d(TAG, "movePinnedStack() animation done");
+                    if (DEBUG) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: movePinnedStack() animation done", TAG);
+                    }
                     mTvPipMenuController.updateExpansionState();
                 });
     }
@@ -336,7 +367,10 @@
      */
     @Override
     public void closePip() {
-        if (DEBUG) Log.d(TAG, "closePip(), state=" + stateToName(mState));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: closePip(), state=%s", TAG, stateToName(mState));
+        }
 
         removeTask(mPinnedTaskId);
         onPipDisappeared();
@@ -348,7 +382,10 @@
 
     private void checkIfPinnedTaskAppeared() {
         final TaskInfo pinnedTask = getPinnedTaskInfo();
-        if (DEBUG) Log.d(TAG, "checkIfPinnedTaskAppeared(), task=" + pinnedTask);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: checkIfPinnedTaskAppeared(), task=%s", TAG, pinnedTask);
+        }
         if (pinnedTask == null || pinnedTask.topActivity == null) return;
         mPinnedTaskId = pinnedTask.taskId;
 
@@ -357,16 +394,23 @@
     }
 
     private void checkIfPinnedTaskIsGone() {
-        if (DEBUG) Log.d(TAG, "onTaskStackChanged()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onTaskStackChanged()", TAG);
+        }
 
         if (isPipShown() && getPinnedTaskInfo() == null) {
-            Log.w(TAG, "Pinned task is gone.");
+            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: Pinned task is gone.", TAG);
             onPipDisappeared();
         }
     }
 
     private void onPipDisappeared() {
-        if (DEBUG) Log.d(TAG, "onPipDisappeared() state=" + stateToName(mState));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onPipDisappeared() state=%s", TAG, stateToName(mState));
+        }
 
         mPipNotificationController.dismiss();
         mTvPipMenuController.hideMenu();
@@ -377,12 +421,18 @@
 
     @Override
     public void onPipTransitionStarted(int direction, Rect pipBounds) {
-        if (DEBUG) Log.d(TAG, "onPipTransition_Started(), state=" + stateToName(mState));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onPipTransition_Started(), state=%s", TAG, stateToName(mState));
+        }
     }
 
     @Override
     public void onPipTransitionCanceled(int direction) {
-        if (DEBUG) Log.d(TAG, "onPipTransition_Canceled(), state=" + stateToName(mState));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onPipTransition_Canceled(), state=%s", TAG, stateToName(mState));
+        }
     }
 
     @Override
@@ -390,18 +440,25 @@
         if (PipAnimationController.isInPipDirection(direction) && mState == STATE_NO_PIP) {
             setState(STATE_PIP);
         }
-        if (DEBUG) Log.d(TAG, "onPipTransition_Finished(), state=" + stateToName(mState));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onPipTransition_Finished(), state=%s", TAG, stateToName(mState));
+        }
     }
 
     private void setState(@State int state) {
         if (DEBUG) {
-            Log.d(TAG, "setState(), state=" + stateToName(state) + ", prev="
-                    + stateToName(mState));
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: setState(), state=%s, prev=%s",
+                    TAG, stateToName(state), stateToName(mState));
         }
         mState = state;
 
         if (mState == STATE_PIP_MENU) {
-            if (DEBUG) Log.d(TAG, "  > show menu");
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s:  > show menu", TAG);
+            }
             mTvPipMenuController.showMenu();
         }
 
@@ -429,7 +486,10 @@
             public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
                     boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
                 if (task.getWindowingMode() == WINDOWING_MODE_PINNED) {
-                    if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
+                    if (DEBUG) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: onPinnedActivityRestartAttempt()", TAG);
+                    }
 
                     // If the "Pip-ed" Activity is launched again by Launcher or intent, make it
                     // fullscreen.
@@ -445,8 +505,9 @@
                 @Override
                 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
                     if (DEBUG) {
-                        Log.d(TAG, "onImeVisibilityChanged(), visible=" + imeVisible
-                                + ", height=" + imeHeight);
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: onImeVisibilityChanged(), visible=%b, height=%d",
+                                TAG, imeVisible, imeHeight);
                     }
 
                     if (imeVisible == mTvPipBoundsState.isImeShowing()
@@ -464,7 +525,10 @@
 
                 @Override
                 public void onAspectRatioChanged(float ratio) {
-                    if (DEBUG) Log.d(TAG, "onAspectRatioChanged: " + ratio);
+                    if (DEBUG) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: onAspectRatioChanged: %f", TAG, ratio);
+                    }
 
                     boolean ratioChanged = mTvPipBoundsState.getAspectRatio() != ratio;
                     mTvPipBoundsState.setAspectRatio(ratio);
@@ -476,7 +540,10 @@
 
                 @Override
                 public void onExpandedAspectRatioChanged(float ratio) {
-                    if (DEBUG) Log.d(TAG, "onExpandedAspectRatioChanged: " + ratio);
+                    if (DEBUG) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: onExpandedAspectRatioChanged: %f", TAG, ratio);
+                    }
 
                     // 0) No update to the ratio --> don't do anything
 
@@ -526,35 +593,50 @@
 
                 @Override
                 public void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
-                    if (DEBUG) Log.d(TAG, "onActionsChanged()");
+                    if (DEBUG) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "%s: onActionsChanged()", TAG);
+                    }
 
                     mTvPipMenuController.setAppActions(actions);
                 }
             });
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to register pinned stack listener", e);
+            ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: Failed to register pinned stack listener, %s", TAG, e);
         }
     }
 
     private static TaskInfo getPinnedTaskInfo() {
-        if (DEBUG) Log.d(TAG, "getPinnedTaskInfo()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: getPinnedTaskInfo()", TAG);
+        }
         try {
             final TaskInfo taskInfo = ActivityTaskManager.getService().getRootTaskInfo(
                     WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
-            if (DEBUG) Log.d(TAG, "  > taskInfo=" + taskInfo);
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s:   > taskInfo=%s", TAG, taskInfo);
+            }
             return taskInfo;
         } catch (RemoteException e) {
-            Log.e(TAG, "getRootTaskInfo() failed", e);
+            ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: getRootTaskInfo() failed, %s", TAG, e);
             return null;
         }
     }
 
     private static void removeTask(int taskId) {
-        if (DEBUG) Log.d(TAG, "removeTask(), taskId=" + taskId);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: removeTask(), taskId=%d", TAG, taskId);
+        }
         try {
             ActivityTaskManager.getService().removeTask(taskId);
         } catch (Exception e) {
-            Log.e(TAG, "Atm.removeTask() failed", e);
+            ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: Atm.removeTask() failed, %s", TAG, e);
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
index b3c2306..1a035c5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
@@ -30,17 +30,18 @@
 import android.graphics.RectF;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.util.Log;
 import android.view.SurfaceControl;
 import android.view.SyncRtSurfaceTransactionApplier;
 import android.view.WindowManagerGlobal;
 
 import androidx.annotation.Nullable;
 
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.SystemWindows;
 import com.android.wm.shell.pip.PipMediaController;
 import com.android.wm.shell.pip.PipMenuController;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -110,7 +111,10 @@
     }
 
     void setDelegate(Delegate delegate) {
-        if (DEBUG) Log.d(TAG, "setDelegate(), delegate=" + delegate);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: setDelegate(), delegate=%s", TAG, delegate);
+        }
         if (mDelegate != null) {
             throw new IllegalStateException(
                     "The delegate has already been set and should not change.");
@@ -133,7 +137,10 @@
     }
 
     private void attachPipMenuView() {
-        if (DEBUG) Log.d(TAG, "attachPipMenuView()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: attachPipMenuView()", TAG);
+        }
 
         if (mPipMenuView != null) {
             detachPipMenuView();
@@ -148,7 +155,10 @@
 
     @Override
     public void showMenu() {
-        if (DEBUG) Log.d(TAG, "showMenu()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: showMenu()", TAG);
+        }
 
         if (mPipMenuView != null) {
             Rect menuBounds = getMenuBounds(mTvPipBoundsState.getBounds());
@@ -189,10 +199,16 @@
 
     void hideMenu() {
         if (!isMenuVisible()) {
-            if (DEBUG) Log.d(TAG, "hideMenu() - Menu isn't visible, so don't hide");
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: hideMenu() - Menu isn't visible, so don't hide", TAG);
+            }
             return;
         } else {
-            if (DEBUG) Log.d(TAG, "hideMenu()");
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: hideMenu()", TAG);
+            }
         }
 
         mPipMenuView.hide();
@@ -208,7 +224,10 @@
 
     @Override
     public void onEnterMoveMode() {
-        if (DEBUG) Log.d(TAG, "onEnterMoveMode - " + mInMoveMode);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onEnterMoveMode - %b", TAG, mInMoveMode);
+        }
         mInMoveMode = true;
         mPipMenuView.showMenuButtons(false);
         mPipMenuView.showMovementHints(mDelegate.getPipGravity());
@@ -217,7 +236,10 @@
 
     @Override
     public boolean onExitMoveMode() {
-        if (DEBUG) Log.d(TAG, "onExitMoveMode - " + mInMoveMode);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onExitMoveMode - %b", TAG, mInMoveMode);
+        }
         if (mInMoveMode) {
             mInMoveMode = false;
             mPipMenuView.showMenuButtons(true);
@@ -230,7 +252,10 @@
 
     @Override
     public boolean onPipMovement(int keycode) {
-        if (DEBUG) Log.d(TAG, "onPipMovement - " + mInMoveMode);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onPipMovement - %b", TAG, mInMoveMode);
+        }
         if (mInMoveMode) {
             mDelegate.movePip(keycode);
         }
@@ -246,12 +271,18 @@
 
     @Override
     public void setAppActions(ParceledListSlice<RemoteAction> actions) {
-        if (DEBUG) Log.d(TAG, "setAppActions()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: setAppActions()", TAG);
+        }
         updateAdditionalActionsList(mAppActions, actions.getList());
     }
 
     private void onMediaActionsChanged(List<RemoteAction> actions) {
-        if (DEBUG) Log.d(TAG, "onMediaActionsChanged()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: onMediaActionsChanged()", TAG);
+        }
 
         // Hide disabled actions.
         List<RemoteAction> enabledActions = new ArrayList<>();
@@ -292,7 +323,10 @@
     @Override
     public boolean isMenuVisible() {
         boolean isVisible = mPipMenuView != null && mPipMenuView.isVisible();
-        if (DEBUG) Log.d(TAG, "isMenuVisible: " + isVisible);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: isMenuVisible: %b", TAG, isVisible);
+        }
         return isVisible;
     }
 
@@ -303,7 +337,10 @@
     public void resizePipMenu(@android.annotation.Nullable SurfaceControl pipLeash,
             @android.annotation.Nullable SurfaceControl.Transaction t,
             Rect destinationBounds) {
-        if (DEBUG) Log.d(TAG, "resizePipMenu: " + destinationBounds.toShortString());
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: resizePipMenu: %s", TAG, destinationBounds.toShortString());
+        }
         if (destinationBounds.isEmpty()) {
             return;
         }
@@ -335,10 +372,16 @@
     @Override
     public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction transaction,
             Rect pipDestBounds) {
-        if (DEBUG) Log.d(TAG, "movePipMenu: " + pipDestBounds.toShortString());
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: movePipMenu: %s", TAG, pipDestBounds.toShortString());
+        }
 
         if (pipDestBounds.isEmpty()) {
-            if (transaction == null && DEBUG) Log.d(TAG, "no transaction given");
+            if (transaction == null && DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: no transaction given", TAG);
+            }
             return;
         }
         if (!maybeCreateSyncApplier()) {
@@ -351,10 +394,16 @@
         // resizing and the PiP menu is also resized. We then want to do a scale from the current
         // new menu bounds.
         if (pipLeash != null && transaction != null) {
-            if (DEBUG) Log.d(TAG, "mTmpSourceBounds based on mPipMenuView.getBoundsOnScreen()");
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: mTmpSourceBounds based on mPipMenuView.getBoundsOnScreen()", TAG);
+            }
             mPipMenuView.getBoundsOnScreen(mTmpSourceBounds);
         } else {
-            if (DEBUG) Log.d(TAG, "mTmpSourceBounds based on menu width and height");
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: mTmpSourceBounds based on menu width and height", TAG);
+            }
             mTmpSourceBounds.set(0, 0, menuDestBounds.width(), menuDestBounds.height());
         }
 
@@ -389,7 +438,8 @@
 
     private boolean maybeCreateSyncApplier() {
         if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) {
-            Log.v(TAG, "Not going to move PiP, either menu or its parent is not created.");
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: Not going to move PiP, either menu or its parent is not created.", TAG);
             return false;
         }
 
@@ -412,7 +462,10 @@
     @Override
     public void updateMenuBounds(Rect destinationBounds) {
         Rect menuBounds = getMenuBounds(destinationBounds);
-        if (DEBUG) Log.d(TAG, "updateMenuBounds: " + menuBounds.toShortString());
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: updateMenuBounds: %s", TAG, menuBounds.toShortString());
+        }
         mSystemWindows.updateViewLayout(mPipMenuView,
                 getPipMenuLayoutParams(MENU_WINDOW_TITLE, menuBounds.width(),
                         menuBounds.height()));
@@ -423,7 +476,7 @@
 
     @Override
     public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
-        Log.d(TAG, "onFocusTaskChanged");
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: onFocusTaskChanged", TAG);
     }
 
     @Override
@@ -465,13 +518,17 @@
     }
 
     private void grantPipMenuFocus(boolean grantFocus) {
-        if (DEBUG) Log.d(TAG, "grantWindowFocus(" + grantFocus + ")");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: grantWindowFocus(%b)", TAG, grantFocus);
+        }
 
         try {
             WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */,
                     mSystemWindows.getFocusGrantToken(mPipMenuView), grantFocus);
         } catch (Exception e) {
-            Log.e(TAG, "Unable to update focus", e);
+            ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: Unable to update focus, %s", TAG, e);
         }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
index 3090139..984dea2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
@@ -31,7 +31,6 @@
 import android.graphics.Rect;
 import android.os.Handler;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.SurfaceControl;
@@ -45,7 +44,9 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.R;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -118,17 +119,24 @@
     }
 
     void updateLayout(Rect updatedBounds) {
-        Log.d(TAG, "update menu layout: " + updatedBounds.toShortString());
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "%s: update menu layout: %s", TAG, updatedBounds.toShortString());
         boolean previouslyVertical =
                 mCurrentBounds != null && mCurrentBounds.height() > mCurrentBounds.width();
         boolean vertical = updatedBounds.height() > updatedBounds.width();
 
         mCurrentBounds = updatedBounds;
         if (previouslyVertical == vertical) {
-            if (DEBUG) Log.d(TAG, "no update for menu layout");
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: no update for menu layout", TAG);
+            }
             return;
         } else {
-            if (DEBUG) Log.d(TAG, "change menu layout to vertical: " + vertical);
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: change menu layout to vertical: %b", TAG, vertical);
+            }
         }
 
         if (vertical) {
@@ -154,7 +162,10 @@
     }
 
     void setIsExpanded(boolean expanded) {
-        if (DEBUG) Log.d(TAG, "setIsExpanded, expanded: " + expanded);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: setIsExpanded, expanded: %b", TAG, expanded);
+        }
         mExpandButton.setImageResource(
                 expanded ? R.drawable.pip_ic_collapse : R.drawable.pip_ic_expand);
         mExpandButton.setTextAndDescription(
@@ -162,7 +173,10 @@
     }
 
     void show(boolean inMoveMode, int gravity) {
-        if (DEBUG) Log.d(TAG, "show(), inMoveMode: " + inMoveMode);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: show(), inMoveMode: %b", TAG, inMoveMode);
+        }
         if (inMoveMode) {
             showMovementHints(gravity);
         } else {
@@ -172,7 +186,9 @@
     }
 
     void hide() {
-        if (DEBUG) Log.d(TAG, "hide()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: hide()", TAG);
+        }
         animateAlphaTo(0, mActionButtonsContainer);
         animateAlphaTo(0, mMenuFrameView);
         hideMovementHints();
@@ -205,7 +221,10 @@
     }
 
     void setAdditionalActions(List<RemoteAction> actions, Handler mainHandler) {
-        if (DEBUG) Log.d(TAG, "setAdditionalActions()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: setAdditionalActions()", TAG);
+        }
 
         // Make sure we exactly as many additional buttons as we have actions to display.
         final int actionsNumber = actions.size();
@@ -278,10 +297,12 @@
                 try {
                     action.getActionIntent().send();
                 } catch (PendingIntent.CanceledException e) {
-                    Log.w(TAG, "Failed to send action", e);
+                    ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                            "%s: Failed to send action, %s", TAG, e);
                 }
             } else {
-                Log.w(TAG, "RemoteAction is null");
+                ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: RemoteAction is null", TAG);
             }
         }
     }
@@ -289,8 +310,9 @@
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
         if (DEBUG) {
-            Log.d(TAG, "dispatchKeyEvent, action: " + event.getAction()
-                    + ", keycode: " + event.getKeyCode());
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: dispatchKeyEvent, action: %d, keycode: %d",
+                    TAG, event.getAction(), event.getKeyCode());
         }
         if (mListener != null && event.getAction() == ACTION_UP) {
             switch (event.getKeyCode()) {
@@ -317,7 +339,10 @@
      * Shows user hints for moving the PiP, e.g. arrows.
      */
     public void showMovementHints(int gravity) {
-        if (DEBUG) Log.d(TAG, "showMovementHints(), position: " + Gravity.toString(gravity));
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: showMovementHints(), position: %s", TAG, Gravity.toString(gravity));
+        }
 
         animateAlphaTo(checkGravity(gravity, Gravity.BOTTOM) ? 1f : 0f, mArrowUp);
         animateAlphaTo(checkGravity(gravity, Gravity.TOP) ? 1f : 0f, mArrowDown);
@@ -333,7 +358,10 @@
      * Hides user hints for moving the PiP, e.g. arrows.
      */
     public void hideMovementHints() {
-        if (DEBUG) Log.d(TAG, "hideMovementHints()");
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: hideMovementHints()", TAG);
+        }
         animateAlphaTo(0, mArrowUp);
         animateAlphaTo(0, mArrowRight);
         animateAlphaTo(0, mArrowDown);
@@ -344,7 +372,10 @@
      * Show or hide the pip user actions.
      */
     public void showMenuButtons(boolean show) {
-        if (DEBUG) Log.d(TAG, "showMenuButtons: " + show);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: showMenuButtons: %b", TAG, show);
+        }
         animateAlphaTo(show ? 1 : 0, mActionButtonsContainer);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java
index dd7e294..7bd3ce9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java
@@ -28,13 +28,13 @@
 import android.graphics.Bitmap;
 import android.media.MediaMetadata;
 import android.os.Handler;
-import android.os.UserHandle;
 import android.text.TextUtils;
-import android.util.Log;
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.R;
 import com.android.wm.shell.pip.PipMediaController;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.util.Objects;
 
@@ -98,7 +98,10 @@
     }
 
     void setDelegate(Delegate delegate) {
-        if (DEBUG) Log.d(TAG, "setDelegate(), delegate=" + delegate);
+        if (DEBUG) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: setDelegate(), delegate=%s", TAG, delegate);
+        }
         if (mDelegate != null) {
             throw new IllegalStateException(
                     "The delegate has already been set and should not change.");
@@ -240,7 +243,10 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
-            if (DEBUG) Log.d(TAG, "on(Broadcast)Receive(), action=" + action);
+            if (DEBUG) {
+                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: on(Broadcast)Receive(), action=%s", TAG, action);
+            }
 
             if (ACTION_SHOW_PIP_MENU.equals(action)) {
                 mDelegate.showPictureInPictureMenu();
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
index 61e27f2..fb404b9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.bubble
 
+import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.uiautomator.By
@@ -24,6 +25,8 @@
 import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.annotation.Group4
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume
 import org.junit.runner.RunWith
 import org.junit.Test
 import org.junit.runners.Parameterized
@@ -69,9 +72,19 @@
             }
         }
 
-    @FlakyTest
+    @Presubmit
     @Test
     fun testAppIsVisibleAtEnd() {
+        Assume.assumeFalse(isShellTransitionsEnabled)
+        testSpec.assertLayersEnd {
+            this.isVisible(testApp.component)
+        }
+    }
+
+    @FlakyTest
+    @Test
+    fun testAppIsVisibleAtEnd_ShellTransit() {
+        Assume.assumeTrue(isShellTransitionsEnabled)
         testSpec.assertLayersEnd {
             this.isVisible(testApp.component)
         }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
index a57d3e6..c43230e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.bubble
 
+import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import android.platform.test.annotations.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -57,9 +58,19 @@
             }
         }
 
-    @FlakyTest(bugId = 218642026)
+    @Presubmit
     @Test
     open fun testAppIsAlwaysVisible() {
+        Assume.assumeFalse(isShellTransitionsEnabled)
+        testSpec.assertLayers {
+            this.isVisible(testApp.component)
+        }
+    }
+
+    @FlakyTest(bugId = 218642026)
+    @Test
+    open fun testAppIsAlwaysVisible_ShellTransit() {
+        Assume.assumeTrue(isShellTransitionsEnabled)
         testSpec.assertLayers {
             this.isVisible(testApp.component)
         }
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
index b6db4cf..9eb4a6c 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
@@ -626,6 +626,7 @@
         /**
          * This is called when the state of the interactive app service is changed.
          *
+         * @param iAppServiceId The ID of the TV Interactive App service.
          * @param type the interactive app type
          * @param state the current state of the service of the given type
          * @param err the error code for error state. {@link #ERROR_NONE} is used when the state is
@@ -815,8 +816,8 @@
      * @param executor A {@link Executor} that the status change will be delivered to.
      */
     public void registerCallback(
-            @NonNull TvInteractiveAppCallback callback,
-            @CallbackExecutor @NonNull Executor executor) {
+            @CallbackExecutor @NonNull Executor executor,
+            @NonNull TvInteractiveAppCallback callback) {
         Preconditions.checkNotNull(callback);
         Preconditions.checkNotNull(executor);
         synchronized (mLock) {
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index bb6edf5..d22fd83 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -16,6 +16,7 @@
 
 package android.media.tv.interactive;
 
+import android.annotation.CallSuper;
 import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -351,6 +352,7 @@
          * @param enable {@code true} if you want to enable the media view. {@code false}
          *            otherwise.
          */
+        @CallSuper
         public void setMediaViewEnabled(final boolean enable) {
             mHandler.post(new Runnable() {
                 @Override
@@ -467,11 +469,11 @@
          * in {@link #onSetSurface}. This method is always called at least once, after
          * {@link #onSetSurface} is called with non-null surface.
          *
-         * @param format The new PixelFormat of the surface.
+         * @param format The new {@link PixelFormat} of the surface.
          * @param width The new width of the surface.
          * @param height The new height of the surface.
          */
-        public void onSurfaceChanged(int format, int width, int height) {
+        public void onSurfaceChanged(@PixelFormat.Format int format, int width, int height) {
         }
 
         /**
@@ -631,6 +633,7 @@
          * @param right Right position in pixels, relative to the overlay view.
          * @param bottom Bottom position in pixels, relative to the overlay view.
          */
+        @CallSuper
         public void layoutSurface(final int left, final int top, final int right,
                 final int bottom) {
             if (left > right || top > bottom) {
@@ -659,6 +662,7 @@
          * Requests broadcast related information from the related TV input.
          * @param request the request for broadcast info
          */
+        @CallSuper
         public void requestBroadcastInfo(@NonNull final BroadcastInfoRequest request) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -683,6 +687,7 @@
          * Remove broadcast information request from the related TV input.
          * @param requestId the ID of the request
          */
+        @CallSuper
         public void removeBroadcastInfo(final int requestId) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -709,6 +714,7 @@
          * @param cmdType type of the specific command
          * @param parameters parameters of the specific command
          */
+        @CallSuper
         public void sendPlaybackCommandRequest(
                 @PlaybackCommandType @NonNull String cmdType, @Nullable Bundle parameters) {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -733,6 +739,7 @@
         /**
          * Sets broadcast video bounds.
          */
+        @CallSuper
         public void setVideoBounds(@NonNull Rect rect) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -755,6 +762,7 @@
         /**
          * Requests the URI of the current channel.
          */
+        @CallSuper
         public void requestCurrentChannelUri() {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -777,6 +785,7 @@
         /**
          * Requests the logic channel number (LCN) of the current channel.
          */
+        @CallSuper
         public void requestCurrentChannelLcn() {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -799,6 +808,7 @@
         /**
          * Requests stream volume.
          */
+        @CallSuper
         public void requestStreamVolume() {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -821,6 +831,7 @@
         /**
          * Requests the list of {@link TvTrackInfo}.
          */
+        @CallSuper
         public void requestTrackInfoList() {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -845,6 +856,7 @@
          *
          * @see android.media.tv.TvInputInfo
          */
+        @CallSuper
         public void requestCurrentTvInputId() {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -869,6 +881,7 @@
          *
          * @param request The advertisement request
          */
+        @CallSuper
         public void requestAd(@NonNull final AdRequest request) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -1032,6 +1045,7 @@
          *            used when the state is not
          *            {@link TvInteractiveAppManager#INTERACTIVE_APP_STATE_ERROR}.
          */
+        @CallSuper
         public void notifySessionStateChanged(
                 @TvInteractiveAppManager.InteractiveAppState int state,
                 @TvInteractiveAppManager.ErrorCode int err) {
@@ -1062,6 +1076,7 @@
          *
          * @see #onCreateBiInteractiveApp(Uri, Bundle)
          */
+        @CallSuper
         public final void notifyBiInteractiveAppCreated(
                 @NonNull Uri biIAppUri, @Nullable String biIAppId) {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -1087,6 +1102,7 @@
          * Notifies when the digital teletext app state is changed.
          * @param state the current state.
          */
+        @CallSuper
         public final void notifyTeletextAppStateChanged(
                 @TvInteractiveAppManager.TeletextAppState int state) {
             executeOrPostRunnableOnMainThread(new Runnable() {
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
index 6652780..217a1f67c3 100644
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ b/packages/ConnectivityT/framework-t/Android.bp
@@ -154,17 +154,17 @@
     ],
 }
 
+// TODO: remove this empty filegroup.
 filegroup {
     name: "framework-connectivity-tiramisu-sources",
-    srcs: [
-        ":framework-connectivity-ethernet-sources",
-    ],
+    srcs: [],
     visibility: ["//frameworks/base"],
 }
 
 filegroup {
     name: "framework-connectivity-tiramisu-updatable-sources",
     srcs: [
+        ":framework-connectivity-ethernet-sources",
         ":framework-connectivity-ipsec-sources",
         ":framework-connectivity-netstats-sources",
         ":framework-connectivity-nsd-sources",
diff --git a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
index 9bffbfb..61b34d0 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
@@ -34,8 +34,9 @@
     private ConnectivityFrameworkInitializerTiramisu() {}
 
     /**
-     * Called by {@link SystemServiceRegistry}'s static initializer and registers nsd services to
-     * {@link Context}, so that {@link Context#getSystemService} can return them.
+     * Called by {@link SystemServiceRegistry}'s static initializer and registers NetworkStats, nsd,
+     * ipsec and ethernet services to {@link Context}, so that {@link Context#getSystemService} can
+     * return them.
      *
      * @throws IllegalStateException if this is called anywhere besides
      * {@link SystemServiceRegistry}.
@@ -68,5 +69,14 @@
                     return new NetworkStatsManager(context, service);
                 }
         );
+
+        SystemServiceRegistry.registerContextAwareService(
+                Context.ETHERNET_SERVICE,
+                EthernetManager.class,
+                (context, serviceBinder) -> {
+                    IEthernetManager service = IEthernetManager.Stub.asInterface(serviceBinder);
+                    return new EthernetManager(context, service);
+                }
+        );
     }
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
index eba51c1..793f28d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
@@ -33,7 +33,7 @@
 import android.os.RemoteException;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.os.BackgroundThread;
+import com.android.modules.utils.BackgroundThread;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp
index 5100e7c..4b799c5 100644
--- a/packages/ConnectivityT/service/Android.bp
+++ b/packages/ConnectivityT/service/Android.bp
@@ -102,17 +102,16 @@
     ],
     path: "src",
     visibility: [
-        "//frameworks/opt/net/ethernet",
+        "//frameworks/opt/net/ethernet/tests",
     ],
 }
 
 // Connectivity-T common libraries.
 
+// TODO: remove this empty filegroup.
 filegroup {
     name: "services.connectivity-tiramisu-sources",
-    srcs: [
-        ":services.connectivity-ethernet-sources",
-    ],
+    srcs: [],
     path: "src",
     visibility: ["//frameworks/base/services/core"],
 }
@@ -120,6 +119,7 @@
 filegroup {
     name: "services.connectivity-tiramisu-updatable-sources",
     srcs: [
+        ":services.connectivity-ethernet-sources",
         ":services.connectivity-ipsec-sources",
         ":services.connectivity-netstats-sources",
         ":services.connectivity-nsd-sources",
diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
similarity index 92%
rename from services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
rename to packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
index 2f77126..ad0be58 100644
--- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
+++ b/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
@@ -48,10 +48,16 @@
  */
 @RunWith(AndroidJUnit4.class)
 public class IpConfigStoreTest {
+    private static final int KEY_CONFIG = 17;
+    private static final String IFACE_1 = "eth0";
+    private static final String IFACE_2 = "eth1";
+    private static final String IP_ADDR_1 = "192.168.1.10/24";
+    private static final String IP_ADDR_2 = "192.168.1.20/24";
+    private static final String DNS_IP_ADDR_1 = "1.2.3.4";
+    private static final String DNS_IP_ADDR_2 = "5.6.7.8";
 
     @Test
     public void backwardCompatibility2to3() throws IOException {
-        final int KEY_CONFIG = 17;
         ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
         DataOutputStream outputStream = new DataOutputStream(byteStream);
 
@@ -73,13 +79,6 @@
 
     @Test
     public void staticIpMultiNetworks() throws Exception {
-        final String IFACE_1 = "eth0";
-        final String IFACE_2 = "eth1";
-        final String IP_ADDR_1 = "192.168.1.10/24";
-        final String IP_ADDR_2 = "192.168.1.20/24";
-        final String DNS_IP_ADDR_1 = "1.2.3.4";
-        final String DNS_IP_ADDR_2 = "5.6.7.8";
-
         final ArrayList<InetAddress> dnsServers = new ArrayList<>();
         dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1));
         dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2));
@@ -144,11 +143,11 @@
 
     /** Synchronously writes into given byte steam */
     private static class MockedDelayedDiskWrite extends DelayedDiskWrite {
-        final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+        final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream();
 
         @Override
         public void write(String filePath, Writer w) {
-            DataOutputStream outputStream = new DataOutputStream(byteStream);
+            DataOutputStream outputStream = new DataOutputStream(mByteStream);
 
             try {
                 w.onWriteCalled(outputStream);
diff --git a/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml b/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml
index 8f6753a..da4088f 100644
--- a/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml
+++ b/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml
@@ -36,6 +36,7 @@
         android:tooltipText="@*android:string/share"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintTop_toTopOf="@+id/copy_button"
+        android:tint="?android:attr/textColorPrimary"
         android:src="@drawable/ic_screenshot_share" />
 
     <ScrollView
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index 28f21af..0529cdbc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -183,7 +183,7 @@
     @Override
     void resetState() {
         mPasswordEntry.setTextOperationUser(UserHandle.of(KeyguardUpdateMonitor.getCurrentUser()));
-        mMessageAreaController.setMessage(R.string.keyguard_enter_your_password);
+        mMessageAreaController.setMessage("");
         final boolean wasDisabled = mPasswordEntry.isEnabled();
         mView.setPasswordEntryEnabled(true);
         mView.setPasswordEntryInputEnabled(true);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index 7635f919..41f9240 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -358,7 +358,7 @@
     }
 
     private void displayDefaultSecurityMessage() {
-        mMessageAreaController.setMessage(R.string.keyguard_enter_your_pattern);
+        mMessageAreaController.setMessage("");
     }
 
     private void handleAttemptLockout(long elapsedRealtimeDeadline) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
index cc7e4f7..f7423ed 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -132,7 +132,6 @@
     @Override
     void resetState() {
         mView.setPasswordEntryEnabled(true);
-        mMessageAreaController.setMessage(R.string.keyguard_enter_your_pin);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index 160d82a..9f4585f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -76,6 +76,12 @@
     }
 
     @Override
+    void resetState() {
+        super.resetState();
+        mMessageAreaController.setMessage("");
+    }
+
+    @Override
     public boolean startDisappearAnimation(Runnable finishRunnable) {
         return mView.startDisappearAnimation(
                 mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable);
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 370686a..74659f7 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -558,7 +558,7 @@
         switch(event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
             case MotionEvent.ACTION_HOVER_ENTER:
-                if (!mDownDetected) {
+                if (!mDownDetected && mAccessibilityManager.isTouchExplorationEnabled()) {
                     mVibrator.vibrate(
                             Process.myUid(),
                             getContext().getOpPackageName(),
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index bf42db5..bc7a3f6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -584,16 +584,18 @@
     }
 
     /**
-     * Play haptic to signal udfps scanning started.
+     * If a11y touchExplorationEnabled, play haptic to signal UDFPS scanning started.
      */
     @VisibleForTesting
     public void playStartHaptic() {
-        mVibrator.vibrate(
-                Process.myUid(),
-                mContext.getOpPackageName(),
-                EFFECT_CLICK,
-                "udfps-onStart-click",
-                VIBRATION_ATTRIBUTES);
+        if (mAccessibilityManager.isTouchExplorationEnabled()) {
+            mVibrator.vibrate(
+                    Process.myUid(),
+                    mContext.getOpPackageName(),
+                    EFFECT_CLICK,
+                    "udfps-onStart-click",
+                    VIBRATION_ATTRIBUTES);
+        }
     }
 
     @Nullable
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
index 508262d..835025b 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.charging;
 
+import static com.android.systemui.charging.WirelessChargingLayout.UNKNOWN_BATTERY_LEVEL;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -76,6 +78,16 @@
     }
 
     /**
+     * Creates a charging animation object using mostly default values for non-dozing and unknown
+     * battery level without charging number shown.
+     */
+    public static WirelessChargingAnimation makeChargingAnimationWithNoBatteryLevel(
+            @NonNull Context context, UiEventLogger uiEventLogger) {
+        return makeWirelessChargingAnimation(context, null,
+                UNKNOWN_BATTERY_LEVEL, UNKNOWN_BATTERY_LEVEL, null, false, uiEventLogger);
+    }
+
+    /**
      * Show the view for the specified duration.
      */
     public void show(long delay) {
diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java b/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java
index e26c768..8000bdc 100644
--- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java
@@ -160,14 +160,15 @@
      * Returns true if lock screen entry point for QR Code Scanner is to be enabled.
      */
     public boolean isEnabledForLockScreenButton() {
-        return mQRCodeScannerEnabled && mIntent != null && mConfigEnableLockScreenButton;
+        return mQRCodeScannerEnabled && mIntent != null && mConfigEnableLockScreenButton
+                && isActivityCallable(mIntent);
     }
 
     /**
      * Returns true if quick settings entry point for QR Code Scanner is to be enabled.
      */
     public boolean isEnabledForQuickSettings() {
-        return mIntent != null;
+        return mIntent != null && isActivityCallable(mIntent);
     }
 
     /**
@@ -278,7 +279,7 @@
             intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
         }
 
-        if (isActivityCallable(intent)) {
+        if (isActivityAvailable(intent)) {
             mQRCodeScannerActivity = qrCodeScannerActivity;
             mComponentName = componentName;
             mIntent = intent;
@@ -293,7 +294,7 @@
         }
     }
 
-    private boolean isActivityCallable(Intent intent) {
+    private boolean isActivityAvailable(Intent intent) {
         // Our intent should always be explicit and should have a component set
         if (intent.getComponent() == null) return false;
 
@@ -307,6 +308,17 @@
                 flags).isEmpty();
     }
 
+    private boolean isActivityCallable(Intent intent) {
+        // Our intent should always be explicit and should have a component set
+        if (intent.getComponent() == null) return false;
+
+        int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE
+                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
+        return !mContext.getPackageManager().queryIntentActivities(intent,
+                flags).isEmpty();
+    }
+
     private void unregisterUserChangeObservers() {
         mUserTracker.removeCallback(mUserChangedListener);
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 32515a2..4cacbba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -15,26 +15,22 @@
  */
 package com.android.systemui.qs.external;
 
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Icon;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.service.quicksettings.IQSService;
 import android.service.quicksettings.Tile;
-import android.service.quicksettings.TileService;
 import android.util.ArrayMap;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.internal.statusbar.StatusBarIcon;
@@ -42,6 +38,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -51,6 +48,7 @@
 import java.util.Objects;
 
 import javax.inject.Inject;
+import javax.inject.Provider;
 
 /**
  * Runs the day-to-day operations of which tiles should be bound and when.
@@ -64,11 +62,12 @@
     private final ArrayMap<ComponentName, CustomTile> mTiles = new ArrayMap<>();
     private final ArrayMap<IBinder, CustomTile> mTokenMap = new ArrayMap<>();
     private final Context mContext;
-    private final Handler mHandler;
     private final Handler mMainHandler;
+    private final Provider<Handler> mHandlerProvider;
     private final QSTileHost mHost;
     private final KeyguardStateController mKeyguardStateController;
     private final BroadcastDispatcher mBroadcastDispatcher;
+    private final CommandQueue mCommandQueue;
     private final UserTracker mUserTracker;
 
     private int mMaxBound = DEFAULT_MAX_BOUND;
@@ -76,23 +75,20 @@
     @Inject
     public TileServices(
             QSTileHost host,
-            @Main Looper looper,
+            @Main Provider<Handler> handlerProvider,
             BroadcastDispatcher broadcastDispatcher,
             UserTracker userTracker,
-            KeyguardStateController keyguardStateController) {
+            KeyguardStateController keyguardStateController,
+            CommandQueue commandQueue) {
         mHost = host;
         mKeyguardStateController = keyguardStateController;
         mContext = mHost.getContext();
         mBroadcastDispatcher = broadcastDispatcher;
-        mHandler = new Handler(looper);
-        mMainHandler = new Handler(Looper.getMainLooper());
+        mHandlerProvider = handlerProvider;
+        mMainHandler = mHandlerProvider.get();
         mUserTracker = userTracker;
-        mBroadcastDispatcher.registerReceiver(
-                mRequestListeningReceiver,
-                new IntentFilter(TileService.ACTION_REQUEST_LISTENING),
-                null, // Use the default Executor
-                UserHandle.ALL
-        );
+        mCommandQueue = commandQueue;
+        mCommandQueue.addCallback(mRequestListeningCallback);
     }
 
     public Context getContext() {
@@ -118,7 +114,7 @@
 
     protected TileServiceManager onCreateTileService(ComponentName component,
             BroadcastDispatcher broadcastDispatcher) {
-        return new TileServiceManager(this, mHandler, component,
+        return new TileServiceManager(this, mHandlerProvider.get(), component,
                 broadcastDispatcher, mUserTracker);
     }
 
@@ -354,21 +350,14 @@
     public void destroy() {
         synchronized (mServices) {
             mServices.values().forEach(service -> service.handleDestroy());
-            mBroadcastDispatcher.unregisterReceiver(mRequestListeningReceiver);
         }
+        mCommandQueue.removeCallback(mRequestListeningCallback);
     }
 
-    private final BroadcastReceiver mRequestListeningReceiver = new BroadcastReceiver() {
+    private final CommandQueue.Callbacks mRequestListeningCallback = new CommandQueue.Callbacks() {
         @Override
-        public void onReceive(Context context, Intent intent) {
-            if (TileService.ACTION_REQUEST_LISTENING.equals(intent.getAction())) {
-                try {
-                    ComponentName c = intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME);
-                    requestListening(c);
-                } catch (ClassCastException ex) {
-                    Log.e(TAG, "Bad component name", ex);
-                }
-            }
+        public void requestTileServiceListeningState(@NonNull ComponentName componentName) {
+            mMainHandler.post(() -> requestListening(componentName));
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 5932a64..d9a98b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -163,6 +163,7 @@
     private static final int MSG_MEDIA_TRANSFER_RECEIVER_STATE = 65 << MSG_SHIFT;
     private static final int MSG_REGISTER_NEARBY_MEDIA_DEVICE_PROVIDER = 66 << MSG_SHIFT;
     private static final int MSG_UNREGISTER_NEARBY_MEDIA_DEVICE_PROVIDER = 67 << MSG_SHIFT;
+    private static final int MSG_TILE_SERVICE_REQUEST_LISTENING_STATE = 68 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -433,6 +434,11 @@
         default void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {}
 
         /**
+         * @see IStatusBar#requestTileServiceListeningState
+         */
+        default void requestTileServiceListeningState(@NonNull ComponentName componentName) {}
+
+        /**
          * @see IStatusBar#requestAddTile
          */
         default void requestAddTile(
@@ -1190,6 +1196,12 @@
     }
 
     @Override
+    public void requestTileServiceListeningState(@NonNull ComponentName componentName) {
+        mHandler.obtainMessage(MSG_TILE_SERVICE_REQUEST_LISTENING_STATE, componentName)
+                .sendToTarget();
+    }
+
+    @Override
     public void requestAddTile(
             @NonNull ComponentName componentName,
             @NonNull CharSequence appName,
@@ -1686,6 +1698,12 @@
                         mCallbacks.get(i).unregisterNearbyMediaDevicesProvider(provider);
                     }
                     break;
+                case MSG_TILE_SERVICE_REQUEST_LISTENING_STATE:
+                    ComponentName component = (ComponentName) msg.obj;
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).requestTileServiceListeningState(component);
+                    }
+                    break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
index 2c1296f..7fbb0f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
@@ -22,15 +22,18 @@
     private val headsUpManager: HeadsUpManagerPhone,
     private val jankMonitor: InteractionJankMonitor
 ) {
+    @JvmOverloads
     fun getAnimatorController(
-        notification: ExpandableNotificationRow
+        notification: ExpandableNotificationRow,
+        onFinishAnimationCallback: Runnable = Runnable {}
     ): NotificationLaunchAnimatorController {
         return NotificationLaunchAnimatorController(
             notificationShadeWindowViewController,
             notificationListContainer,
             headsUpManager,
             notification,
-            jankMonitor
+            jankMonitor,
+            onFinishAnimationCallback
         )
     }
 }
@@ -45,7 +48,8 @@
     private val notificationListContainer: NotificationListContainer,
     private val headsUpManager: HeadsUpManagerPhone,
     private val notification: ExpandableNotificationRow,
-    private val jankMonitor: InteractionJankMonitor
+    private val jankMonitor: InteractionJankMonitor,
+    private val onFinishAnimationCallback: Runnable
 ) : ActivityLaunchAnimator.Controller {
 
     companion object {
@@ -119,6 +123,7 @@
 
         if (!willAnimate) {
             removeHun(animate = true)
+            onFinishAnimationCallback.run()
         }
     }
 
@@ -137,6 +142,7 @@
         notificationShadeWindowViewController.setExpandAnimationRunning(false)
         notificationEntry.isExpandAnimationRunning = false
         removeHun(animate = true)
+        onFinishAnimationCallback.run()
     }
 
     override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
@@ -156,6 +162,7 @@
         notificationListContainer.setExpandingNotification(null)
         applyParams(null)
         removeHun(animate = false)
+        onFinishAnimationCallback.run()
     }
 
     private fun applyParams(params: ExpandAnimationParameters?) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index 0df2162..da0169b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -72,10 +72,11 @@
     private var mEndLifetimeExtension: OnEndLifetimeExtensionCallback? = null
     private lateinit var mNotifPipeline: NotifPipeline
     private var mNow: Long = -1
-    // notifs we've extended the lifetime for
-    private val mNotifsExtendingLifetime = ArraySet<NotificationEntry>()
     private val mPostedEntries = LinkedHashMap<String, PostedEntry>()
 
+    // notifs we've extended the lifetime for with cancellation callbacks
+    private val mNotifsExtendingLifetime = ArrayMap<NotificationEntry, Runnable?>()
+
     override fun attach(pipeline: NotifPipeline) {
         mNotifPipeline = pipeline
         mHeadsUpManager.addListener(mOnHeadsUpChangedListener)
@@ -460,23 +461,20 @@
             }
             if (isSticky(entry)) {
                 val removeAfterMillis = mHeadsUpManager.getEarliestRemovalTime(entry.key)
-                mExecutor.executeDelayed({
-                    val canStillRemove = mHeadsUpManager.canRemoveImmediately(entry.key)
-                    if (mNotifsExtendingLifetime.contains(entry) && canStillRemove) {
-                        mHeadsUpManager.removeNotification(entry.key, /* releaseImmediately */ true)
-                    }
+                mNotifsExtendingLifetime[entry] = mExecutor.executeDelayed({
+                    mHeadsUpManager.removeNotification(entry.key, /* releaseImmediately */ true)
                 }, removeAfterMillis)
             } else {
                 mExecutor.execute {
                     mHeadsUpManager.removeNotification(entry.key, /* releaseImmediately */ false)
                 }
+                mNotifsExtendingLifetime[entry] = null
             }
-            mNotifsExtendingLifetime.add(entry)
             return true
         }
 
         override fun cancelLifetimeExtension(entry: NotificationEntry) {
-            mNotifsExtendingLifetime.remove(entry)
+            mNotifsExtendingLifetime.remove(entry)?.run()
         }
     }
 
@@ -543,7 +541,8 @@
         mPostedEntries[entry.key]?.calculateShouldBeHeadsUpStrict ?: isAttemptingToShowHun(entry)
 
     private fun endNotifLifetimeExtensionIfExtended(entry: NotificationEntry) {
-        if (mNotifsExtendingLifetime.remove(entry)) {
+        if (mNotifsExtendingLifetime.contains(entry)) {
+            mNotifsExtendingLifetime.remove(entry)?.run()
             mEndLifetimeExtension?.onEndLifetimeExtension(mLifetimeExtender, entry)
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
index cd2affe..7c4e449 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
@@ -73,7 +73,7 @@
         GroupExpansionManager,
         Dumpable {
 
-    private static final String TAG = "NotifGroupManager";
+    private static final String TAG = "LegacyNotifGroupManager";
     private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
     private static final boolean SPEW = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index a7f950e..ec2d608 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -2881,8 +2881,7 @@
     }
 
     boolean updateIsKeyguard(boolean forceStateChange) {
-        boolean wakeAndUnlocking = mBiometricUnlockController.getMode()
-                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
+        boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock();
 
         // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise
         // there's no surface we can show to the user. Note that the device goes fully interactive
@@ -2892,7 +2891,7 @@
                 && (!mDeviceInteractive || (isGoingToSleep()
                     && (isScreenFullyOff()
                         || (mKeyguardStateController.isShowing() && !isOccluded()))));
-        boolean isWakingAndOccluded = isOccluded() && isWaking();
+        boolean isWakingAndOccluded = isOccluded() && isWakingOrAwake();
         boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
                 || keyguardForDozing) && !wakeAndUnlocking && !isWakingAndOccluded;
         if (keyguardForDozing) {
@@ -3076,7 +3075,6 @@
         mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
         releaseGestureWakeLock();
         mNotificationPanelViewController.onAffordanceLaunchEnded();
-        mNotificationPanelViewController.cancelAnimation();
         mNotificationPanelViewController.resetAlpha();
         mNotificationPanelViewController.resetTranslation();
         mNotificationPanelViewController.resetViewGroupFade();
@@ -3702,8 +3700,9 @@
                 == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
     }
 
-    boolean isWaking() {
-        return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING;
+    boolean isWakingOrAwake() {
+        return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING
+                || mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_AWAKE;
     }
 
     public void notifyBiometricAuthModeChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
index 0ff010a..16e5732 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
@@ -386,10 +386,12 @@
             }
             visible = true;
         }
-        if (visible) {
-            mNotificationShadeView.setVisibility(View.VISIBLE);
-        } else {
-            mNotificationShadeView.setVisibility(View.INVISIBLE);
+        if (mNotificationShadeView != null) {
+            if (visible) {
+                mNotificationShadeView.setVisibility(View.VISIBLE);
+            } else {
+                mNotificationShadeView.setVisibility(View.INVISIBLE);
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 108d98a..637e4be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -370,6 +370,8 @@
             mLogger.logExpandingBubble(notificationKey);
             removeHunAfterClick(row);
             expandBubbleStackOnMainThread(entry);
+            mMainThreadHandler.post(
+                    () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry));
         } else {
             startNotificationIntent(intent, fillInIntent, entry, row, animate, isActivityIntent);
         }
@@ -395,7 +397,6 @@
             mMainThreadHandler.post(() -> {
                 final Runnable removeNotification = () -> {
                     mOnUserInteractionCallback.onDismiss(entry, REASON_CLICK, summaryToRemove);
-                    mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry);
                 };
                 if (mPresenter.isCollapsing()) {
                     // To avoid lags we're only performing the remove
@@ -405,9 +406,6 @@
                     removeNotification.run();
                 }
             });
-        } else {
-            mMainThreadHandler.post(
-                    () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry));
         }
 
         mIsCollapsingToShowActivityOverLockscreen = false;
@@ -483,14 +481,19 @@
             boolean isActivityIntent) {
         mLogger.logStartNotificationIntent(entry.getKey(), intent);
         try {
+            Runnable onFinishAnimationCallback =
+                    () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry);
             ActivityLaunchAnimator.Controller animationController =
                     new StatusBarLaunchAnimatorController(
-                            mNotificationAnimationProvider.getAnimatorController(row),
+                            mNotificationAnimationProvider
+                                    .getAnimatorController(row, onFinishAnimationCallback),
                             mCentralSurfaces,
                             isActivityIntent);
-
-            mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController,
-                    animate, intent.getCreatorPackage(), (adapter) -> {
+            mActivityLaunchAnimator.startPendingIntentWithAnimation(
+                    animationController,
+                    animate,
+                    intent.getCreatorPackage(),
+                    (adapter) -> {
                         long eventTime = row.getAndResetLastActionUpTime();
                         Bundle options = eventTime > 0
                                 ? getActivityOptions(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
index e980eb7..8e1e42a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
@@ -88,6 +88,6 @@
     fun onPause_clearsTextField() {
         mKeyguardPatternViewController.init()
         mKeyguardPatternViewController.onPause()
-        verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern)
+        verify(mKeyguardMessageAreaController).setMessage("")
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 1856fda..613931f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -48,6 +48,7 @@
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
+import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
 
@@ -64,8 +65,8 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
@@ -188,6 +189,7 @@
     @Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor;
     private IUdfpsOverlayController mOverlayController;
     @Captor private ArgumentCaptor<UdfpsView.OnTouchListener> mTouchListenerCaptor;
+    @Captor private ArgumentCaptor<View.OnHoverListener> mHoverListenerCaptor;
     @Captor private ArgumentCaptor<Runnable> mOnIlluminatedRunnableCaptor;
     @Captor private ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor;
     private ScreenLifecycle.Observer mScreenObserver;
@@ -568,23 +570,24 @@
     }
 
     @Test
-    public void playHapticOnTouchUdfpsArea() throws RemoteException {
+    public void playHapticOnTouchUdfpsArea_a11yTouchExplorationEnabled() throws RemoteException {
         // Configure UdfpsView to accept the ACTION_DOWN event
         when(mUdfpsView.isIlluminationRequested()).thenReturn(false);
         when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
 
-        // GIVEN that the overlay is showing
+        // GIVEN that the overlay is showing and a11y touch exploration enabled
+        when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true);
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
                 BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
-        // WHEN ACTION_DOWN is received
-        verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
-        MotionEvent downEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
-        mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent);
-        downEvent.recycle();
-        MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0);
-        mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
+        // WHEN ACTION_HOVER is received
+        verify(mUdfpsView).setOnHoverListener(mHoverListenerCaptor.capture());
+        MotionEvent enterEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0);
+        mHoverListenerCaptor.getValue().onHover(mUdfpsView, enterEvent);
+        enterEvent.recycle();
+        MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0);
+        mHoverListenerCaptor.getValue().onHover(mUdfpsView, moveEvent);
         moveEvent.recycle();
 
         // THEN tick haptic is played
@@ -600,4 +603,34 @@
         assertEquals(VibrationAttributes.USAGE_COMMUNICATION_REQUEST,
                 UdfpsController.VIBRATION_ATTRIBUTES.getUsage());
     }
+
+    @Test
+    public void noHapticOnTouchUdfpsArea_a11yTouchExplorationDisabled() throws RemoteException {
+        // Configure UdfpsView to accept the ACTION_DOWN event
+        when(mUdfpsView.isIlluminationRequested()).thenReturn(false);
+        when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
+
+        // GIVEN that the overlay is showing and a11y touch exploration NOT enabled
+        when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);
+        mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+        mFgExecutor.runAllReady();
+
+        // WHEN ACTION_DOWN is received
+        verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
+        MotionEvent downEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
+        mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent);
+        downEvent.recycle();
+        MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0);
+        mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
+        moveEvent.recycle();
+
+        // THEN NO haptic played
+        verify(mVibrator, never()).vibrate(
+                anyInt(),
+                anyString(),
+                any(),
+                anyString(),
+                any());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 19a9863..6b7e5b93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -20,21 +20,18 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.os.Handler;
-import android.os.Looper;
+import android.os.RemoteException;
 import android.os.UserHandle;
-import android.service.quicksettings.TileService;
+import android.service.quicksettings.IQSTileService;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -49,6 +46,7 @@
 import com.android.systemui.qs.tileimpl.QSFactoryImpl;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -68,17 +66,25 @@
 import java.util.ArrayList;
 import java.util.Optional;
 
+import javax.inject.Provider;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 public class TileServicesTest extends SysuiTestCase {
     private static int NUM_FAKES = TileServices.DEFAULT_MAX_BOUND * 2;
 
+    private static final ComponentName TEST_COMPONENT =
+            ComponentName.unflattenFromString("pkg/.cls");
+
     private TileServices mTileService;
+    private TestableLooper mTestableLooper;
     private ArrayList<TileServiceManager> mManagers;
     @Mock
     private BroadcastDispatcher mBroadcastDispatcher;
     @Mock
+    private CommandQueue mCommandQueue;
+    @Mock
     private StatusBarIconController mStatusBarIconController;
     @Mock
     private QSFactoryImpl mQSFactory;
@@ -116,17 +122,20 @@
         MockitoAnnotations.initMocks(this);
         mDependency.injectMockDependency(BluetoothController.class);
         mManagers = new ArrayList<>();
+        mTestableLooper = TestableLooper.get(this);
 
         when(mTileServiceRequestControllerBuilder.create(any()))
                 .thenReturn(mTileServiceRequestController);
         when(mTileLifecycleManagerFactory.create(any(Intent.class), any(UserHandle.class)))
                 .thenReturn(mTileLifecycleManager);
 
+        Provider<Handler> provider = () -> new Handler(mTestableLooper.getLooper());
+
         QSTileHost host = new QSTileHost(mContext,
                 mStatusBarIconController,
                 mQSFactory,
-                new Handler(),
-                Looper.myLooper(),
+                provider.get(),
+                mTestableLooper.getLooper(),
                 mPluginManager,
                 mTunerService,
                 () -> mAutoTileManager,
@@ -140,8 +149,8 @@
                 mock(CustomTileStatePersister.class),
                 mTileServiceRequestControllerBuilder,
                 mTileLifecycleManagerFactory);
-        mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher,
-                mUserTracker, mKeyguardStateController);
+        mTileService = new TestTileServices(host, provider, mBroadcastDispatcher,
+                mUserTracker, mKeyguardStateController, mCommandQueue);
     }
 
     @After
@@ -152,24 +161,6 @@
     }
 
     @Test
-    public void testActiveTileListenerRegisteredOnAllUsers() {
-        ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
-        verify(mBroadcastDispatcher).registerReceiver(any(), captor.capture(), any(), eq(
-                UserHandle.ALL));
-        assertTrue(captor.getValue().hasAction(TileService.ACTION_REQUEST_LISTENING));
-    }
-
-    @Test
-    public void testBadComponentName_doesntCrash() {
-        ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class);
-        verify(mBroadcastDispatcher).registerReceiver(captor.capture(), any(), any(), eq(
-                UserHandle.ALL));
-        Intent intent = new Intent(TileService.ACTION_REQUEST_LISTENING)
-                .putExtra(Intent.EXTRA_COMPONENT_NAME, "abc");
-        captor.getValue().onReceive(mContext, intent);
-    }
-
-    @Test
     public void testRecalculateBindAllowance() {
         // Add some fake tiles.
         for (int i = 0; i < NUM_FAKES; i++) {
@@ -225,11 +216,36 @@
         }
     }
 
+    @Test
+    public void testRegisterCommand() {
+        verify(mCommandQueue).addCallback(any());
+    }
+
+    @Test
+    public void testRequestListeningStatusCommand() throws RemoteException {
+        ArgumentCaptor<CommandQueue.Callbacks> captor =
+                ArgumentCaptor.forClass(CommandQueue.Callbacks.class);
+        verify(mCommandQueue).addCallback(captor.capture());
+
+        CustomTile mockTile = mock(CustomTile.class);
+        when(mockTile.getComponent()).thenReturn(TEST_COMPONENT);
+
+        TileServiceManager manager = mTileService.getTileWrapper(mockTile);
+        when(manager.isActiveTile()).thenReturn(true);
+        when(manager.getTileService()).thenReturn(mock(IQSTileService.class));
+
+        captor.getValue().requestTileServiceListeningState(TEST_COMPONENT);
+        mTestableLooper.processAllMessages();
+        verify(manager).setBindRequested(true);
+        verify(manager.getTileService()).onStartListening();
+    }
+
     private class TestTileServices extends TileServices {
-        TestTileServices(QSTileHost host, Looper looper,
+        TestTileServices(QSTileHost host, Provider<Handler> handlerProvider,
                 BroadcastDispatcher broadcastDispatcher, UserTracker userTracker,
-                KeyguardStateController keyguardStateController) {
-            super(host, looper, broadcastDispatcher, userTracker, keyguardStateController);
+                KeyguardStateController keyguardStateController, CommandQueue commandQueue) {
+            super(host, handlerProvider, broadcastDispatcher, userTracker, keyguardStateController,
+                    commandQueue);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
index 3a60c04..9f82a567 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
@@ -31,6 +31,7 @@
     @Mock lateinit var notificationListContainer: NotificationListContainer
     @Mock lateinit var headsUpManager: HeadsUpManagerPhone
     @Mock lateinit var jankMonitor: InteractionJankMonitor
+    @Mock lateinit var onFinishAnimationCallback: Runnable
 
     private lateinit var notificationTestHelper: NotificationTestHelper
     private lateinit var notification: ExpandableNotificationRow
@@ -52,7 +53,8 @@
                 notificationListContainer,
                 headsUpManager,
                 notification,
-                jankMonitor
+                jankMonitor,
+                onFinishAnimationCallback
         )
     }
 
@@ -61,7 +63,7 @@
     }
 
     @Test
-    fun testHunIsRemovedIfWeDontAnimateLaunch() {
+    fun testHunIsRemovedAndCallbackIsInvokedIfWeDontAnimateLaunch() {
         flagNotificationAsHun()
         controller.onIntentStarted(willAnimate = false)
 
@@ -69,10 +71,11 @@
         assertFalse(notification.entry.isExpandAnimationRunning)
         verify(headsUpManager).removeNotification(
                 notificationKey, true /* releaseImmediately */, true /* animate */)
+        verify(onFinishAnimationCallback).run()
     }
 
     @Test
-    fun testHunIsRemovedWhenAnimationIsCancelled() {
+    fun testHunIsRemovedAndCallbackIsInvokedWhenAnimationIsCancelled() {
         flagNotificationAsHun()
         controller.onLaunchAnimationCancelled()
 
@@ -80,10 +83,11 @@
         assertFalse(notification.entry.isExpandAnimationRunning)
         verify(headsUpManager).removeNotification(
                 notificationKey, true /* releaseImmediately */, true /* animate */)
+        verify(onFinishAnimationCallback).run()
     }
 
     @Test
-    fun testHunIsRemovedWhenAnimationEnds() {
+    fun testHunIsRemovedAndCallbackIsInvokedWhenAnimationEnds() {
         flagNotificationAsHun()
         controller.onLaunchAnimationEnd(isExpandingFullyAbove = true)
 
@@ -91,6 +95,7 @@
         assertFalse(notification.entry.isExpandAnimationRunning)
         verify(headsUpManager).removeNotification(
                 notificationKey, true /* releaseImmediately */, false /* animate */)
+        verify(onFinishAnimationCallback).run()
     }
 
     @Test
@@ -99,4 +104,4 @@
 
         assertTrue(notification.entry.isExpandAnimationRunning)
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
index 144eefb..699f77f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
@@ -170,11 +170,41 @@
     }
 
     @Test
+    fun testCancelAndReAddStickyNotification() {
+        whenever(mHeadsUpManager.isSticky(anyString())).thenReturn(true)
+        addHUN(mEntry)
+        whenever(mHeadsUpManager.canRemoveImmediately(anyString())).thenReturn(false, true, false)
+        whenever(mHeadsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L)
+        assertTrue(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0))
+        addHUN(mEntry)
+        assertFalse(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0))
+        mExecutor.advanceClockToLast()
+        mExecutor.runAllReady()
+        assertTrue(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0))
+        verify(mHeadsUpManager, times(0)).removeNotification(anyString(), eq(false))
+        verify(mHeadsUpManager, times(0)).removeNotification(anyString(), eq(true))
+    }
+
+    @Test
+    fun hunNotRemovedWhenExtensionCancelled() {
+        whenever(mHeadsUpManager.isSticky(anyString())).thenReturn(true)
+        addHUN(mEntry)
+        whenever(mHeadsUpManager.canRemoveImmediately(anyString())).thenReturn(false)
+        whenever(mHeadsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L)
+        assertTrue(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0))
+        mNotifLifetimeExtender.cancelLifetimeExtension(mEntry)
+        mExecutor.advanceClockToLast()
+        mExecutor.runAllReady()
+        verify(mHeadsUpManager, times(0)).removeNotification(anyString(), any())
+    }
+
+    @Test
     fun testCancelUpdatedStickyNotification() {
         whenever(mHeadsUpManager.isSticky(anyString())).thenReturn(true)
         addHUN(mEntry)
         whenever(mHeadsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L, 500L)
         assertTrue(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0))
+        addHUN(mEntry)
         mExecutor.advanceClockToLast()
         mExecutor.runAllReady()
         verify(mHeadsUpManager, times(0)).removeNotification(anyString(), eq(false))
@@ -305,6 +335,7 @@
         mHuns.add(entry)
         whenever(mHeadsUpManager.topEntry).thenReturn(entry)
         mOnHeadsUpChangedListener.onHeadsUpStateChanged(entry, true)
+        mNotifLifetimeExtender.cancelLifetimeExtension(entry)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 27179fd..d48ce8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -85,6 +85,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.Mockito;
@@ -188,10 +189,11 @@
         when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
         when(mOnUserInteractionCallback.getGroupSummaryToDismiss(mNotificationRow.getEntry()))
                 .thenReturn(null);
-        when(mVisibilityProvider.obtain(anyString(), anyBoolean())).thenAnswer(
-                invocation-> NotificationVisibility.obtain(invocation.getArgument(0), 0, 1, false));
-        when(mVisibilityProvider.obtain(any(NotificationEntry.class), anyBoolean())).thenAnswer(
-                invocation-> NotificationVisibility.obtain(
+        when(mVisibilityProvider.obtain(anyString(), anyBoolean()))
+                .thenAnswer(invocation -> NotificationVisibility.obtain(
+                        invocation.getArgument(0), 0, 1, false));
+        when(mVisibilityProvider.obtain(any(NotificationEntry.class), anyBoolean()))
+                .thenAnswer(invocation -> NotificationVisibility.obtain(
                         invocation.<NotificationEntry>getArgument(0).getKey(), 0, 1, false));
 
         HeadsUpManagerPhone headsUpManager = mock(HeadsUpManagerPhone.class);
@@ -431,12 +433,18 @@
     }
 
     @Test
-    public void testNotifActivityStarterEventSourceFinishEvent_postPanelCollapse() {
+    public void testNotifActivityStarterEventSourceFinishEvent_postPanelCollapse()
+            throws Exception {
         NotifActivityLaunchEvents.Listener listener =
                 mock(NotifActivityLaunchEvents.Listener.class);
         mLaunchEventsEmitter.registerListener(listener);
         mNotificationActivityStarter
                 .onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow);
+        ArgumentCaptor<ActivityLaunchAnimator.Controller> controllerCaptor =
+                ArgumentCaptor.forClass(ActivityLaunchAnimator.Controller.class);
+        verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(
+                controllerCaptor.capture(), anyBoolean(), any(), any());
+        controllerCaptor.getValue().onIntentStarted(false);
         verify(listener).onFinishLaunchNotifActivity(mNotificationRow.getEntry());
     }
 }
diff --git a/services/api/current.txt b/services/api/current.txt
index 45c0059..5a28802 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -38,7 +38,7 @@
 package com.android.server.am {
 
   public interface ActivityManagerLocal {
-    method public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, int) throws android.os.RemoteException;
+    method public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, @NonNull String, int) throws android.os.RemoteException;
     method public boolean canStartForegroundService(int, int, @NonNull String);
   }
 
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 58fa9fb..839cdc6 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -91,7 +91,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
-import com.android.internal.telephony.ICarrierPrivilegesListener;
+import com.android.internal.telephony.ICarrierPrivilegesCallback;
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 import com.android.internal.telephony.IPhoneStateListener;
 import com.android.internal.telephony.ITelephonyRegistry;
@@ -153,7 +153,7 @@
         IPhoneStateListener callback;
         IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
         IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
-        ICarrierPrivilegesListener carrierPrivilegesListener;
+        ICarrierPrivilegesCallback carrierPrivilegesCallback;
 
         int callerUid;
         int callerPid;
@@ -178,8 +178,8 @@
             return (onOpportunisticSubscriptionsChangedListenerCallback != null);
         }
 
-        boolean matchCarrierPrivilegesListener() {
-            return carrierPrivilegesListener != null;
+        boolean matchCarrierPrivilegesCallback() {
+            return carrierPrivilegesCallback != null;
         }
 
         boolean canReadCallLog() {
@@ -199,7 +199,7 @@
                     + onSubscriptionsChangedListenerCallback
                     + " onOpportunisticSubscriptionsChangedListenererCallback="
                     + onOpportunisticSubscriptionsChangedListenerCallback
-                    + " carrierPrivilegesListener=" + carrierPrivilegesListener
+                    + " carrierPrivilegesCallback=" + carrierPrivilegesCallback
                     + " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}";
         }
     }
@@ -414,7 +414,9 @@
             mPreciseDataConnectionStates;
 
     /** Per-phoneId snapshot of privileged packages (names + UIDs). */
-    private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates;
+    @NonNull private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates;
+    /** Per-phoneId of CarrierService (PackageName, UID) pair. */
+    @NonNull private List<Pair<String, Integer>> mCarrierServiceStates;
 
     /**
      * Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}.
@@ -705,6 +707,7 @@
                 cutListToSize(mPhysicalChannelConfigs, mNumPhones);
                 cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
                 cutListToSize(mCarrierPrivilegeStates, mNumPhones);
+                cutListToSize(mCarrierServiceStates, mNumPhones);
                 return;
             }
 
@@ -746,6 +749,7 @@
                 mAllowedNetworkTypeValue[i] = -1;
                 mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
                 mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
+                mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID));
             }
         }
     }
@@ -813,6 +817,7 @@
         mDataEnabledReason = new int[numPhones];
         mLinkCapacityEstimateLists = new ArrayList<>();
         mCarrierPrivilegeStates = new ArrayList<>();
+        mCarrierServiceStates = new ArrayList<>();
 
         for (int i = 0; i < numPhones; i++) {
             mCallState[i] =  TelephonyManager.CALL_STATE_IDLE;
@@ -851,6 +856,7 @@
             mAllowedNetworkTypeValue[i] = -1;
             mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
             mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
+            mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID));
         }
 
         mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -2784,16 +2790,16 @@
     }
 
     @Override
-    public void addCarrierPrivilegesListener(
+    public void addCarrierPrivilegesCallback(
             int phoneId,
-            ICarrierPrivilegesListener callback,
-            String callingPackage,
-            String callingFeatureId) {
+            @NonNull ICarrierPrivilegesCallback callback,
+            @NonNull String callingPackage,
+            @NonNull String callingFeatureId) {
         int callerUserId = UserHandle.getCallingUserId();
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
-                "addCarrierPrivilegesListener");
+                "addCarrierPrivilegesCallback");
         if (VDBG) {
             log(
                     "listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId
@@ -2813,7 +2819,7 @@
             if (r == null) return;
 
             r.context = mContext;
-            r.carrierPrivilegesListener = callback;
+            r.carrierPrivilegesCallback = callback;
             r.callingPackage = callingPackage;
             r.callingFeatureId = callingFeatureId;
             r.callerUid = Binder.getCallingUid();
@@ -2825,10 +2831,18 @@
             }
 
             Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId);
+            Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(phoneId);
             try {
-                r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
-                        Collections.unmodifiableList(state.first),
-                        Arrays.copyOf(state.second, state.second.length));
+                if (r.matchCarrierPrivilegesCallback()) {
+                    // Here, two callbacks are triggered in quick succession on the same binder.
+                    // In typical case, we expect the callers to care about only one or the other.
+                    r.carrierPrivilegesCallback.onCarrierPrivilegesChanged(
+                            Collections.unmodifiableList(state.first),
+                            Arrays.copyOf(state.second, state.second.length));
+
+                    r.carrierPrivilegesCallback.onCarrierServiceChanged(carrierServiceState.first,
+                            carrierServiceState.second);
+                }
             } catch (RemoteException ex) {
                 remove(r.binder);
             }
@@ -2836,12 +2850,12 @@
     }
 
     @Override
-    public void removeCarrierPrivilegesListener(
-            ICarrierPrivilegesListener callback, String callingPackage) {
+    public void removeCarrierPrivilegesCallback(
+            @NonNull ICarrierPrivilegesCallback callback, @NonNull String callingPackage) {
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
-                "removeCarrierPrivilegesListener");
+                "removeCarrierPrivilegesCallback");
         remove(callback.asBinder());
     }
 
@@ -2866,13 +2880,13 @@
             for (Record r : mRecords) {
                 // Listeners are per-slot, not per-subscription. This is to provide a stable
                 // view across SIM profile switches.
-                if (!r.matchCarrierPrivilegesListener()
+                if (!r.matchCarrierPrivilegesCallback()
                         || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) {
                     continue;
                 }
                 try {
                     // Make sure even in-process listeners can't modify the values.
-                    r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
+                    r.carrierPrivilegesCallback.onCarrierPrivilegesChanged(
                             Collections.unmodifiableList(privilegedPackageNames),
                             Arrays.copyOf(privilegedUids, privilegedUids.length));
                 } catch (RemoteException ex) {
@@ -2883,6 +2897,34 @@
         }
     }
 
+    @Override
+    public void notifyCarrierServiceChanged(int phoneId, @Nullable String packageName, int uid) {
+        if (!checkNotifyPermission("notifyCarrierServiceChanged")) return;
+        if (!validatePhoneId(phoneId)) return;
+        if (VDBG) {
+            log("notifyCarrierServiceChanged: phoneId=" + phoneId
+                    + ", package=" + pii(packageName) + ", uid=" + uid);
+        }
+
+        synchronized (mRecords) {
+            mCarrierServiceStates.set(
+                    phoneId, new Pair<>(packageName, uid));
+            for (Record r : mRecords) {
+                // Listeners are per-slot, not per-subscription.
+                if (!r.matchCarrierPrivilegesCallback()
+                        || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) {
+                    continue;
+                }
+                try {
+                    r.carrierPrivilegesCallback.onCarrierServiceChanged(packageName, uid);
+                } catch (RemoteException ex) {
+                    mRemoveList.add(r.binder);
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
     @NeverCompile // Avoid size overhead of debugging code.
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
@@ -2938,6 +2980,9 @@
                 pw.println(
                         "mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first)
                                 + ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">");
+                Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(i);
+                pw.println("mCarrierServiceState=<package=" + pii(carrierServiceState.first)
+                        + ", uid=" + carrierServiceState.second + ">");
                 pw.decreaseIndent();
             }
 
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d4ad718..48e3264 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2722,7 +2722,7 @@
     int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
             String resolvedType, final IServiceConnection connection, int flags,
             String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
-            String callingPackage, final int userId)
+            String sdkSandboxClientAppPackage, String callingPackage, final int userId)
             throws TransactionTooLargeException {
         if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
                 + " type=" + resolvedType + " conn=" + connection.asBinder()
@@ -2807,8 +2807,9 @@
         final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
 
         ServiceLookupResult res = retrieveServiceLocked(service, instanceName,
-                isSdkSandboxService, sdkSandboxClientAppUid, resolvedType, callingPackage,
-                callingPid, callingUid, userId, true, callerFg, isBindExternal, allowInstant);
+                isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
+                resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg,
+                isBindExternal, allowInstant);
         if (res == null) {
             return 0;
         }
@@ -3228,14 +3229,14 @@
             int callingPid, int callingUid, int userId,
             boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
             boolean allowInstant) {
-        return retrieveServiceLocked(service, instanceName, false, 0, resolvedType, callingPackage,
-                callingPid, callingUid, userId, createIfNeeded, callingFromFg, isBindExternal,
-                allowInstant);
+        return retrieveServiceLocked(service, instanceName, false, 0, null, resolvedType,
+                callingPackage, callingPid, callingUid, userId, createIfNeeded, callingFromFg,
+                isBindExternal, allowInstant);
     }
 
     private ServiceLookupResult retrieveServiceLocked(Intent service,
             String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
-            String resolvedType,
+            String sdkSandboxClientAppPackage, String resolvedType,
             String callingPackage, int callingPid, int callingUid, int userId,
             boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
             boolean allowInstant) {
@@ -3416,7 +3417,8 @@
                                                                                   : null;
                     r = new ServiceRecord(mAm, className, name, definingPackageName,
                             definingUid, filter, sInfo, callingFromFg, res,
-                            sdkSandboxProcessName, sdkSandboxClientAppUid);
+                            sdkSandboxProcessName, sdkSandboxClientAppUid,
+                            sdkSandboxClientAppPackage);
                     res.setService(r);
                     smap.mServicesByInstanceName.put(name, r);
                     smap.mServicesByIntent.put(filter, r);
@@ -4195,7 +4197,7 @@
             if (r.isSdkSandbox) {
                 final int uid = Process.toSdkSandboxUid(r.sdkSandboxClientAppUid);
                 app = mAm.startSdkSandboxProcessLocked(procName, r.appInfo, true, intentFlags,
-                        hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, uid);
+                        hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, uid, r.sdkSandboxClientAppPackage);
                 r.isolationHostProc = app;
             } else {
                 app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
diff --git a/services/core/java/com/android/server/am/ActivityManagerLocal.java b/services/core/java/com/android/server/am/ActivityManagerLocal.java
index 3226a2b..1d2c36b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerLocal.java
+++ b/services/core/java/com/android/server/am/ActivityManagerLocal.java
@@ -74,6 +74,8 @@
      * @param conn Receives information as the service is started and stopped.
      *        This must be a valid ServiceConnection object; it must not be null.
      * @param clientAppUid Uid of the app for which the sdk sandbox process needs to be spawned.
+     * @param clientAppPackage Package of the app for which the sdk sandbox process needs to
+     *        be spawned. This package must belong to the clientAppUid.
      * @param processName Unique identifier for the service instance. Each unique name here will
      *        result in a different service instance being created. Identifiers must only contain
      *        ASCII letters, digits, underscores, and periods.
@@ -87,6 +89,7 @@
      */
     @SuppressLint("RethrowRemoteException")
     boolean bindSdkSandboxService(@NonNull Intent service, @NonNull ServiceConnection conn,
-            int clientAppUid, @NonNull String processName, @Context.BindServiceFlags int flags)
+            int clientAppUid, @NonNull String clientAppPackage, @NonNull String processName,
+            @Context.BindServiceFlags int flags)
             throws RemoteException;
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 95e35ef..0735648 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -36,6 +36,7 @@
 import static android.app.ActivityManager.StopUserOnSwitch;
 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
+import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_NONE;
 import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
 import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES;
@@ -1895,6 +1896,7 @@
                         0,
                         false,
                         0,
+                        null,
                         new HostingRecord("system"));
                 app.setPersistent(true);
                 app.setPid(MY_PID);
@@ -2783,7 +2785,8 @@
                     false /* knownToBeDead */, 0 /* intentFlags */,
                     sNullHostingRecord  /* hostingRecord */, ZYGOTE_POLICY_FLAG_EMPTY,
                     true /* allowWhileBooting */, true /* isolated */,
-                    uid, false /* supplemental */, 0 /* supplementalUid */,
+                    uid, false /* isSdkSandbox */, 0 /* sdkSandboxUid */,
+                    null /* sdkSandboxClientAppPackage */,
                     abiOverride, entryPoint, entryPointArgs, crashHandler);
             return proc != null;
         }
@@ -2792,11 +2795,12 @@
     @GuardedBy("this")
     final ProcessRecord startSdkSandboxProcessLocked(String processName,
             ApplicationInfo info, boolean knownToBeDead, int intentFlags,
-            HostingRecord hostingRecord, int zygotePolicyFlags, int sdkSandboxUid) {
+            HostingRecord hostingRecord, int zygotePolicyFlags, int sdkSandboxUid,
+            String sdkSandboxClientAppPackage) {
         return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                 hostingRecord, zygotePolicyFlags, false /* allowWhileBooting */,
                 false /* isolated */, 0 /* isolatedUid */,
-                true /* isSdkSandbox */, sdkSandboxUid,
+                true /* isSdkSandbox */, sdkSandboxUid, sdkSandboxClientAppPackage,
                 null /* ABI override */, null /* entryPoint */,
                 null /* entryPointArgs */, null /* crashHandler */);
     }
@@ -2808,7 +2812,8 @@
             boolean isolated) {
         return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                 hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
-                false /* isSdkSandbox */, 0 /* sdkSandboxClientdAppUid */,
+                false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,
+                null /* sdkSandboxClientAppPackage */,
                 null /* ABI override */, null /* entryPoint */,
                 null /* entryPointArgs */, null /* crashHandler */);
     }
@@ -4773,7 +4778,8 @@
                 thread.runIsolatedEntryPoint(
                         app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
             } else if (instr2 != null) {
-                thread.bindApplication(processName, appInfo, providerList,
+                thread.bindApplication(processName, appInfo, app.sdkSandboxClientAppPackage,
+                        providerList,
                         instr2.mClass,
                         profilerInfo, instr2.mArguments,
                         instr2.mWatcher,
@@ -4787,8 +4793,8 @@
                         app.getDisabledCompatChanges(), serializedSystemFontMap,
                         app.getStartElapsedTime(), app.getStartUptime());
             } else {
-                thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
-                        null, null, null, testMode,
+                thread.bindApplication(processName, appInfo, app.sdkSandboxClientAppPackage,
+                        providerList, null, profilerInfo, null, null, null, testMode,
                         mBinderTransactionTrackingEnabled, enableTrackAllocation,
                         isRestrictedBackupMode || !normalMode, app.isPersistent(),
                         new Configuration(app.getWindowProcessController().getConfiguration()),
@@ -5749,6 +5755,18 @@
                 owningUid, exported);
     }
 
+    private void enforceDebuggable(ProcessRecord proc) {
+        if (!Build.IS_DEBUGGABLE && !proc.isDebuggable()) {
+            throw new SecurityException("Process not debuggable: " + proc.info.packageName);
+        }
+    }
+
+    private void enforceDebuggable(ApplicationInfo info) {
+        if (!Build.IS_DEBUGGABLE && (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
+            throw new SecurityException("Process not debuggable: " + info.packageName);
+        }
+    }
+
     /**
      * As the only public entry point for permissions checking, this method
      * can enforce the semantic that requesting a check on a null global
@@ -6553,7 +6571,7 @@
 
         if (app == null) {
             app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0,
-                    false, 0,
+                    false, 0, null,
                     new HostingRecord("added application",
                         customProcess != null ? customProcess : info.processName));
             updateLruProcessLocked(app, false, null);
@@ -6786,22 +6804,25 @@
     }
 
     void setTrackAllocationApp(ApplicationInfo app, String processName) {
-        if (!Build.IS_DEBUGGABLE) {
-            if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
-                throw new SecurityException("Process not debuggable: " + app.packageName);
-            }
-        }
+        enforceDebuggable(app);
 
         synchronized (mProcLock) {
             mTrackAllocationApp = processName;
         }
     }
 
-    void setProfileApp(ApplicationInfo app, String processName, ProfilerInfo profilerInfo) {
+    void setProfileApp(ApplicationInfo app, String processName, ProfilerInfo profilerInfo,
+            ApplicationInfo sdkSandboxClientApp) {
         synchronized (mAppProfiler.mProfilerLock) {
             if (!Build.IS_DEBUGGABLE) {
                 boolean isAppDebuggable = (app.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
                 boolean isAppProfileable = app.isProfileableByShell();
+
+                if (sdkSandboxClientApp != null) {
+                    isAppDebuggable |=
+                            (sdkSandboxClientApp.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+                    isAppProfileable |= sdkSandboxClientApp.isProfileableByShell();
+                }
                 if (!isAppDebuggable && !isAppProfileable) {
                     throw new SecurityException("Process not debuggable, "
                             + "and not profileable by shell: " + app.packageName);
@@ -6812,11 +6833,7 @@
     }
 
     void setNativeDebuggingAppLocked(ApplicationInfo app, String processName) {
-        if (!Build.IS_DEBUGGABLE) {
-            if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
-                throw new SecurityException("Process not debuggable: " + app.packageName);
-            }
-        }
+        enforceDebuggable(app);
         mNativeDebuggingApp = processName;
     }
 
@@ -12395,13 +12412,13 @@
             String resolvedType, IServiceConnection connection, int flags, String instanceName,
             String callingPackage, int userId) throws TransactionTooLargeException {
         return bindServiceInstance(caller, token, service, resolvedType, connection, flags,
-                instanceName, false, 0, callingPackage, userId);
+                instanceName, false, 0, null, callingPackage, userId);
     }
 
     private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
             String resolvedType, IServiceConnection connection, int flags, String instanceName,
-            boolean isSdkSandboxService, int sdkSandboxClientdAppUid, String callingPackage,
-            int userId)
+            boolean isSdkSandboxService, int sdkSandboxClientAppUid,
+            String sdkSandboxClientAppPackage, String callingPackage, int userId)
             throws TransactionTooLargeException {
         enforceNotIsolatedCaller("bindService");
 
@@ -12438,8 +12455,8 @@
             }
             synchronized (this) {
                 return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,
-                        flags, instanceName, isSdkSandboxService, sdkSandboxClientdAppUid,
-                        callingPackage, userId);
+                        flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,
+                        sdkSandboxClientAppPackage, callingPackage, userId);
             }
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -15562,12 +15579,7 @@
                     throw new IllegalArgumentException("Unknown process: " + process);
                 }
 
-                boolean isDebuggable = Build.IS_DEBUGGABLE;
-                if (!isDebuggable) {
-                    if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
-                        throw new SecurityException("Process not debuggable: " + proc);
-                    }
-                }
+                enforceDebuggable(proc);
 
                 mOomAdjuster.mCachedAppOptimizer.enableFreezer(false);
 
@@ -15670,10 +15682,7 @@
                     throw new SecurityException("No process found for calling pid "
                             + Binder.getCallingPid());
                 }
-                if (!Build.IS_DEBUGGABLE
-                        && (proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
-                    throw new SecurityException("Not running a debuggable build");
-                }
+                enforceDebuggable(proc);
                 processName = proc.processName;
                 uid = proc.uid;
                 if (reportPackage != null && !proc.getPkgList().containsKey(reportPackage)) {
@@ -15884,13 +15893,7 @@
             return false;
         }
 
-        if (!Build.IS_DEBUGGABLE) {
-            if ((process.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
-                return false;
-            }
-        }
-
-        return true;
+        return Build.IS_DEBUGGABLE || process.isDebuggable();
     }
 
     public boolean startBinderTracking() throws RemoteException {
@@ -16022,22 +16025,29 @@
 
         @Override
         public boolean bindSdkSandboxService(Intent service, ServiceConnection conn,
-                int userAppUid, String processName, int flags) throws RemoteException {
+                int clientAppUid, String clientAppPackage, String processName, int flags)
+                throws RemoteException {
             if (service == null) {
                 throw new IllegalArgumentException("intent is null");
             }
             if (conn == null) {
                 throw new IllegalArgumentException("connection is null");
             }
+            if (clientAppPackage == null) {
+                throw new IllegalArgumentException("clientAppPackage is null");
+            }
             if (processName == null) {
                 throw new IllegalArgumentException("processName is null");
             }
             if (service.getComponent() == null) {
                 throw new IllegalArgumentException("service must specify explicit component");
             }
-            if (!UserHandle.isApp(userAppUid)) {
+            if (!UserHandle.isApp(clientAppUid)) {
                 throw new IllegalArgumentException("uid is not within application range");
             }
+            if (mAppOpsService.checkPackage(clientAppUid, clientAppPackage) != MODE_ALLOWED) {
+                throw new IllegalArgumentException("uid does not belong to provided package");
+            }
 
             Handler handler = mContext.getMainThreadHandler();
 
@@ -16046,8 +16056,8 @@
             return ActivityManagerService.this.bindServiceInstance(
                     mContext.getIApplicationThread(), mContext.getActivityToken(), service,
                     service.resolveTypeIfNeeded(mContext.getContentResolver()), sd, flags,
-                    processName, /*isSupplementalProcessService*/ true, userAppUid,
-                    mContext.getOpPackageName(), UserHandle.getUserId(userAppUid)) != 0;
+                    processName, /*isSdkSandboxService*/ true, clientAppUid, clientAppPackage,
+                    mContext.getOpPackageName(), UserHandle.getUserId(clientAppUid)) != 0;
         }
 
         @Override
@@ -16837,7 +16847,7 @@
                     }
 
                     if (profilerInfo != null) {
-                        setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
+                        setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo, null);
                     }
                     wmLock.notify();
                 }
@@ -17625,11 +17635,7 @@
                     throw new IllegalArgumentException("Unknown process: " + process);
                 }
 
-                if (!Build.IS_DEBUGGABLE) {
-                    if ((proc.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
-                        throw new SecurityException("Process not debuggable: " + proc);
-                    }
-                }
+                enforceDebuggable(proc);
 
                 thread.attachAgent(path);
             }
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index d6a4cf6..16a7283 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -58,7 +58,6 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
 import android.os.Binder;
@@ -608,13 +607,7 @@
         if (check != null) {
             if ((pss * 1024) >= check && profile.getThread() != null
                     && mMemWatchDumpProcName == null) {
-                boolean isDebuggable = Build.IS_DEBUGGABLE;
-                if (!isDebuggable) {
-                    if ((proc.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
-                        isDebuggable = true;
-                    }
-                }
-                if (isDebuggable) {
+                if (Build.IS_DEBUGGABLE || proc.isDebuggable()) {
                     Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + "; reporting");
                     startHeapDumpLPf(profile, false);
                 } else {
@@ -1702,7 +1695,8 @@
         try {
             if (start) {
                 stopProfilerLPf(null, 0);
-                mService.setProfileApp(proc.info, proc.processName, profilerInfo);
+                mService.setProfileApp(proc.info, proc.processName, profilerInfo,
+                        proc.isSdkSandbox ? proc.getClientInfoForSdkSandbox() : null);
                 mProfileData.setProfileProc(proc);
                 mProfileType = profileType;
                 ParcelFileDescriptor fd = profilerInfo.profileFd;
@@ -1886,8 +1880,7 @@
                                     BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
                                     if (ps == null || !ps.isActive()) {
                                         st.batteryStats = ps = bstats.getProcessStatsLocked(
-                                                bstats.mapUid(st.uid), st.name,
-                                                elapsedRealtime, uptime);
+                                                st.uid, st.name, elapsedRealtime, uptime);
                                     }
                                     ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
                                 }
@@ -2076,7 +2069,7 @@
             if (mAppAgentMap != null && mAppAgentMap.containsKey(processName)) {
                 // We need to do a debuggable check here. See setAgentApp for why the check is
                 // postponed to here.
-                if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+                if (app.isDebuggable()) {
                     String agent = mAppAgentMap.get(processName);
                     // Do not overwrite already requested agent.
                     if (profilerInfo == null) {
@@ -2133,7 +2126,7 @@
         if (preBindAgent != null) {
             thread.attachAgent(preBindAgent);
         }
-        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+        if (app.isDebuggable()) {
             thread.attachStartupAgents(app.info.dataDir);
         }
         return profilerInfo;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 91822ac..eb7897b 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -799,6 +799,7 @@
                     final BatteryUsageStatsQuery querySinceReset =
                             new BatteryUsageStatsQuery.Builder()
                                     .includeProcessStateData()
+                                    .includeVirtualUids()
                                     .build();
                     bus = getBatteryUsageStats(List.of(querySinceReset)).get(0);
                     break;
@@ -806,6 +807,7 @@
                     final BatteryUsageStatsQuery queryPowerProfile =
                             new BatteryUsageStatsQuery.Builder()
                                     .includeProcessStateData()
+                                    .includeVirtualUids()
                                     .powerProfileModeledOnly()
                                     .build();
                     bus = getBatteryUsageStats(List.of(queryPowerProfile)).get(0);
@@ -821,6 +823,7 @@
                     final BatteryUsageStatsQuery queryBeforeReset =
                             new BatteryUsageStatsQuery.Builder()
                                     .includeProcessStateData()
+                                    .includeVirtualUids()
                                     .aggregateSnapshots(sessionStart, sessionEnd)
                                     .build();
                     bus = getBatteryUsageStats(List.of(queryBeforeReset)).get(0);
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 48ca59d..253686c 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1718,8 +1718,16 @@
             int runtimeFlags = 0;
 
             boolean debuggableFlag = (app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
-            if (!debuggableFlag && app.isSdkSandbox) {
-                debuggableFlag = isAppForSdkSandboxDebuggable(app);
+            boolean isProfileableByShell = app.info.isProfileableByShell();
+            boolean isProfileable = app.info.isProfileable();
+
+            if (app.isSdkSandbox) {
+                ApplicationInfo clientInfo = app.getClientInfoForSdkSandbox();
+                if (clientInfo != null) {
+                    debuggableFlag |= (clientInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+                    isProfileableByShell |= clientInfo.isProfileableByShell();
+                    isProfileable |= clientInfo.isProfileable();
+                }
             }
 
             if (debuggableFlag) {
@@ -1741,10 +1749,10 @@
             if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || mService.mSafeMode) {
                 runtimeFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
             }
-            if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL) != 0) {
+            if (isProfileableByShell) {
                 runtimeFlags |= Zygote.PROFILE_FROM_SHELL;
             }
-            if (app.info.isProfileable()) {
+            if (isProfileable) {
                 runtimeFlags |= Zygote.PROFILEABLE;
             }
             if ("1".equals(SystemProperties.get("debug.checkjni"))) {
@@ -1812,7 +1820,7 @@
             }
 
             String invokeWith = null;
-            if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+            if (debuggableFlag) {
                 // Debuggable apps may include a wrapper script with their library directory.
                 String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
                 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
@@ -1887,24 +1895,6 @@
         }
     }
 
-    /** Return true if the client app for the SDK sandbox process is debuggable. */
-    private boolean isAppForSdkSandboxDebuggable(ProcessRecord sandboxProcess) {
-        // TODO (b/221004701) use client app process name
-        final int appUid = Process.getAppUidForSdkSandboxUid(sandboxProcess.uid);
-        IPackageManager pm = mService.getPackageManager();
-        try {
-            String[] packages = pm.getPackagesForUid(appUid);
-            for (String aPackage : packages) {
-                ApplicationInfo i = pm.getApplicationInfo(aPackage, 0, sandboxProcess.userId);
-                if ((i.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
-                    return true;
-                }
-            }
-        } catch (RemoteException e) {
-            // shouldn't happen
-        }
-        return false;
-    }
 
     @GuardedBy("mService")
     boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
@@ -2365,7 +2355,7 @@
     ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
             boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
             int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
-            boolean isSdkSandbox, int sdkSandboxUid,
+            boolean isSdkSandbox, int sdkSandboxUid, String sdkSandboxClientAppPackage,
             String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
         long startTime = SystemClock.uptimeMillis();
         ProcessRecord app;
@@ -2460,7 +2450,7 @@
         if (app == null) {
             checkSlow(startTime, "startProcess: creating new process record");
             app = newProcessRecordLocked(info, processName, isolated, isolatedUid, isSdkSandbox,
-                    sdkSandboxUid, hostingRecord);
+                    sdkSandboxUid, sdkSandboxClientAppPackage, hostingRecord);
             if (app == null) {
                 Slog.w(TAG, "Failed making new process record for "
                         + processName + "/" + info.uid + " isolated=" + isolated);
@@ -2956,7 +2946,7 @@
     @GuardedBy("mService")
     ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
             boolean isolated, int isolatedUid, boolean isSdkSandbox, int sdkSandboxUid,
-            HostingRecord hostingRecord) {
+            String sdkSandboxClientAppPackage, HostingRecord hostingRecord) {
         String proc = customProcess != null ? customProcess : info.processName;
         final int userId = UserHandle.getUserId(info.uid);
         int uid = info.uid;
@@ -2992,6 +2982,7 @@
                     FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
         }
         final ProcessRecord r = new ProcessRecord(mService, info, proc, uid,
+                sdkSandboxClientAppPackage,
                 hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
         final ProcessStateRecord state = r.mState;
 
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index f7cc3d7..b4ff870 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -27,6 +27,7 @@
 import android.app.ApplicationExitInfo.SubReason;
 import android.app.IApplicationThread;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ProcessInfo;
 import android.content.pm.VersionedPackage;
 import android.content.res.CompatibilityInfo;
@@ -84,6 +85,8 @@
     final int uid;              // uid of process; may be different from 'info' if isolated
     final int userId;           // user of process.
     final String processName;   // name of the process
+    final String sdkSandboxClientAppPackage; // if this is an sdk sandbox process, name of the
+                                             // app package for which it is running
 
     /**
      * Overall state of process's uid.
@@ -493,11 +496,12 @@
 
     ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName,
             int _uid) {
-        this(_service, _info, _processName, _uid, -1, null);
+        this(_service, _info, _processName, _uid, null, -1, null);
     }
 
     ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName,
-            int _uid, int _definingUid, String _definingProcessName) {
+            int _uid, String _sdkSandboxClientAppPackage, int _definingUid,
+            String _definingProcessName) {
         mService = _service;
         mProcLock = _service.mProcLock;
         info = _info;
@@ -530,6 +534,7 @@
         uid = _uid;
         userId = UserHandle.getUserId(_uid);
         processName = _processName;
+        sdkSandboxClientAppPackage = _sdkSandboxClientAppPackage;
         mPersistent = false;
         mRemoved = false;
         mProfile = new ProcessProfileRecord(this);
@@ -861,6 +866,29 @@
         return mDebugging;
     }
 
+    @Nullable
+    public ApplicationInfo getClientInfoForSdkSandbox() {
+        if (!isSdkSandbox || sdkSandboxClientAppPackage == null) {
+            throw new IllegalStateException(
+                    "getClientInfoForSdkSandbox called for non-sandbox process"
+            );
+        }
+        PackageManagerInternal pm = mService.getPackageManagerInternal();
+        return pm.getApplicationInfo(
+                sdkSandboxClientAppPackage, /* flags */0, Process.SYSTEM_UID, userId);
+    }
+
+    public boolean isDebuggable() {
+        if ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+            return true;
+        }
+        if (isSdkSandbox) {
+            ApplicationInfo clientInfo = getClientInfoForSdkSandbox();
+            return clientInfo != null && (clientInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+        }
+        return false;
+    }
+
     @GuardedBy("mService")
     void setDebugging(boolean debugging) {
         mDebugging = debugging;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index c53d4d6..795311f 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -96,6 +96,8 @@
     final long createRealTime;  // when this service was created
     final boolean isSdkSandbox; // whether this is a sdk sandbox service
     final int sdkSandboxClientAppUid; // the app uid for which this sdk sandbox service is running
+    final String sdkSandboxClientAppPackage; // the app package for which this sdk sandbox service
+                                             // is running
     final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
             = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
                             // All active bindings to the service.
@@ -573,13 +575,14 @@
             Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg,
             Runnable restarter) {
         this(ams, name, instanceName, definingPackageName, definingUid, intent, sInfo, callerIsFg,
-                restarter, null, 0);
+                restarter, null, 0, null);
     }
 
     ServiceRecord(ActivityManagerService ams, ComponentName name,
             ComponentName instanceName, String definingPackageName, int definingUid,
             Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg,
-            Runnable restarter, String sdkSandboxProcessName, int sdkSandboxClientAppUid) {
+            Runnable restarter, String sdkSandboxProcessName, int sdkSandboxClientAppUid,
+            String sdkSandboxClientAppPackage) {
         this.ams = ams;
         this.name = name;
         this.instanceName = instanceName;
@@ -590,8 +593,9 @@
         serviceInfo = sInfo;
         appInfo = sInfo.applicationInfo;
         packageName = sInfo.applicationInfo.packageName;
-        isSdkSandbox = sdkSandboxProcessName != null;
+        this.isSdkSandbox = sdkSandboxProcessName != null;
         this.sdkSandboxClientAppUid = sdkSandboxClientAppUid;
+        this.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage;
         if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0) {
             processName = sInfo.processName + ":" + instanceName.getClassName();
         } else if (sdkSandboxProcessName != null) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 265ad7d..1885b55 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -630,6 +630,7 @@
     private int mWarnRemoteViewsSizeBytes;
     private int mStripRemoteViewsSizeBytes;
     final boolean mEnableAppSettingMigration;
+    private boolean mForceUserSetOnUpgrade;
 
     private MetricsLogger mMetricsLogger;
     private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
@@ -2294,6 +2295,7 @@
 
         mMsgPkgsAllowedAsConvos = Set.of(getStringArrayResource(
                 com.android.internal.R.array.config_notificationMsgPkgsAllowedAsConvos));
+
         mStatsManager = statsManager;
 
         mToastRateLimiter = toastRateLimiter;
@@ -2386,6 +2388,9 @@
 
         WorkerHandler handler = new WorkerHandler(Looper.myLooper());
 
+        mForceUserSetOnUpgrade = getContext().getResources().getBoolean(
+                R.bool.config_notificationForceUserSetOnUpgrade);
+
         init(handler, new RankingHandlerWorker(mRankingThread.getLooper()),
                 AppGlobals.getPackageManager(), getContext().getPackageManager(),
                 getLocalService(LightsManager.class),
@@ -2414,7 +2419,8 @@
                 LocalServices.getService(ActivityManagerInternal.class),
                 createToastRateLimiter(), new PermissionHelper(LocalServices.getService(
                         PermissionManagerServiceInternal.class), AppGlobals.getPackageManager(),
-                        AppGlobals.getPermissionManager(), mEnableAppSettingMigration),
+                        AppGlobals.getPermissionManager(), mEnableAppSettingMigration,
+                        mForceUserSetOnUpgrade),
                 LocalServices.getService(UsageStatsManagerInternal.class));
 
         publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false,
@@ -6069,6 +6075,7 @@
                     pw.println("  mMaxPackageEnqueueRate=" + mMaxPackageEnqueueRate);
                     pw.println("  hideSilentStatusBar="
                             + mPreferencesHelper.shouldHideSilentStatusIcons());
+                    pw.println("  mForceUserSetOnUpgrade=" + mForceUserSetOnUpgrade);
                 }
                 pw.println("  mArchive=" + mArchive.toString());
                 mArchive.dumpImpl(pw, filter);
diff --git a/services/core/java/com/android/server/notification/PermissionHelper.java b/services/core/java/com/android/server/notification/PermissionHelper.java
index e551f10..b4230c1 100644
--- a/services/core/java/com/android/server/notification/PermissionHelper.java
+++ b/services/core/java/com/android/server/notification/PermissionHelper.java
@@ -57,13 +57,16 @@
     private final IPermissionManager mPermManager;
     // TODO (b/194833441): Remove when the migration is enabled
     private final boolean mMigrationEnabled;
+    private final boolean mForceUserSetOnUpgrade;
 
     public PermissionHelper(PermissionManagerServiceInternal pmi, IPackageManager packageManager,
-            IPermissionManager permManager, boolean migrationEnabled) {
+            IPermissionManager permManager, boolean migrationEnabled,
+            boolean forceUserSetOnUpgrade) {
         mPmi = pmi;
         mPackageManager = packageManager;
         mPermManager = permManager;
         mMigrationEnabled = migrationEnabled;
+        mForceUserSetOnUpgrade = forceUserSetOnUpgrade;
     }
 
     public boolean isMigrationEnabled() {
@@ -223,8 +226,9 @@
             return;
         }
         if (!isPermissionFixed(pkgPerm.packageName, pkgPerm.userId)) {
+            boolean userSet = mForceUserSetOnUpgrade ? true : pkgPerm.userModifiedSettings;
             setNotificationPermission(pkgPerm.packageName, pkgPerm.userId, pkgPerm.granted,
-                    pkgPerm.userSet, !pkgPerm.userSet);
+                    userSet, !userSet);
         }
     }
 
@@ -305,13 +309,13 @@
         public final String packageName;
         public final @UserIdInt int userId;
         public final boolean granted;
-        public final boolean userSet;
+        public final boolean userModifiedSettings;
 
         public PackagePermission(String pkg, int userId, boolean granted, boolean userSet) {
             this.packageName = pkg;
             this.userId = userId;
             this.granted = granted;
-            this.userSet = userSet;
+            this.userModifiedSettings = userSet;
         }
 
         @Override
@@ -319,13 +323,14 @@
             if (this == o) return true;
             if (o == null || getClass() != o.getClass()) return false;
             PackagePermission that = (PackagePermission) o;
-            return userId == that.userId && granted == that.granted && userSet == that.userSet
+            return userId == that.userId && granted == that.granted && userModifiedSettings
+                    == that.userModifiedSettings
                     && Objects.equals(packageName, that.packageName);
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(packageName, userId, granted, userSet);
+            return Objects.hash(packageName, userId, granted, userModifiedSettings);
         }
 
         @Override
@@ -334,7 +339,7 @@
                     "packageName='" + packageName + '\'' +
                     ", userId=" + userId +
                     ", granted=" + granted +
-                    ", userSet=" + userSet +
+                    ", userSet=" + userModifiedSettings +
                     '}';
         }
     }
diff --git a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
index f452b29..91750de 100644
--- a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
@@ -30,6 +30,7 @@
 import static com.android.server.pm.PackageManagerService.SCAN_REQUIRE_KNOWN;
 import static com.android.server.pm.PackageManagerService.SYSTEM_PARTITIONS;
 import static com.android.server.pm.PackageManagerService.TAG;
+import static com.android.server.pm.pkg.parsing.ParsingPackageUtils.PARSE_CHECK_MAX_SDK_VERSION;
 
 import android.annotation.Nullable;
 import android.content.pm.parsing.ApkLiteParseUtils;
@@ -313,10 +314,14 @@
 
     @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
     private void scanDirTracedLI(File scanDir, List<File> frameworkSplits,
-            final int parseFlags, int scanFlags,
+            int parseFlags, int scanFlags,
             long currentTime, PackageParser2 packageParser, ExecutorService executorService) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
         try {
+            if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
+                // when scanning apk in apexes, we want to check the maxSdkVersion
+                parseFlags |= PARSE_CHECK_MAX_SDK_VERSION;
+            }
             mInstallPackageHelper.installPackagesFromDir(scanDir, frameworkSplits, parseFlags,
                     scanFlags, currentTime, packageParser, executorService);
         } finally {
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
index cbba346..40f859c 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
@@ -302,6 +302,8 @@
 
     ParsingPackage setMinSdkVersion(int minSdkVersion);
 
+    ParsingPackage setMaxSdkVersion(int maxSdkVersion);
+
     ParsingPackage setNetworkSecurityConfigRes(int networkSecurityConfigRes);
 
     ParsingPackage setNonLocalizedLabel(CharSequence nonLocalizedLabel);
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java
index 1484df8..67d9aec 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java
@@ -383,6 +383,7 @@
     @Nullable
     private SparseIntArray minExtensionVersions;
     private int minSdkVersion = ParsingUtils.DEFAULT_MIN_SDK_VERSION;
+    private int maxSdkVersion = ParsingUtils.DEFAULT_MAX_SDK_VERSION;
     private int networkSecurityConfigRes;
     @Nullable
     private CharSequence nonLocalizedLabel;
@@ -1306,6 +1307,7 @@
         dest.writeFloat(this.maxAspectRatio);
         dest.writeFloat(this.minAspectRatio);
         dest.writeInt(this.minSdkVersion);
+        dest.writeInt(this.maxSdkVersion);
         dest.writeInt(this.networkSecurityConfigRes);
         dest.writeCharSequence(this.nonLocalizedLabel);
         dest.writeString(this.permission);
@@ -1454,6 +1456,7 @@
         this.maxAspectRatio = in.readFloat();
         this.minAspectRatio = in.readFloat();
         this.minSdkVersion = in.readInt();
+        this.maxSdkVersion = in.readInt();
         this.networkSecurityConfigRes = in.readInt();
         this.nonLocalizedLabel = in.readCharSequence();
         this.permission = in.readString();
@@ -2068,6 +2071,11 @@
     }
 
     @Override
+    public int getMaxSdkVersion() {
+        return maxSdkVersion;
+    }
+
+    @Override
     public int getNetworkSecurityConfigRes() {
         return networkSecurityConfigRes;
     }
@@ -2592,6 +2600,12 @@
     }
 
     @Override
+    public ParsingPackageImpl setMaxSdkVersion(int value) {
+        maxSdkVersion = value;
+        return this;
+    }
+
+    @Override
     public ParsingPackageImpl setNetworkSecurityConfigRes(int value) {
         networkSecurityConfigRes = value;
         return this;
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 112b9e0..b323948 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -209,6 +209,8 @@
 
     public static final int SDK_VERSION = Build.VERSION.SDK_INT;
     public static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
+    public static final String[] PREVIOUS_CODENAMES =
+            Build.VERSION.KNOWN_CODENAMES.toArray(new String[]{});
 
     public static boolean sCompatibilityModeEnabled = true;
     public static boolean sUseRoundIcon = false;
@@ -236,6 +238,7 @@
      */
     public static final int PARSE_IGNORE_OVERLAY_REQUIRED_SYSTEM_PROPERTY = 1 << 7;
     public static final int PARSE_FRAMEWORK_RES_SPLITS = 1 << 8;
+    public static final int PARSE_CHECK_MAX_SDK_VERSION = 1 << 9;
 
     public static final int PARSE_CHATTY = 1 << 31;
 
@@ -1002,7 +1005,7 @@
             case TAG_FEATURE_GROUP:
                 return parseFeatureGroup(input, pkg, res, parser);
             case TAG_USES_SDK:
-                return parseUsesSdk(input, pkg, res, parser);
+                return parseUsesSdk(input, pkg, res, parser, flags);
             case TAG_SUPPORT_SCREENS:
                 return parseSupportScreens(input, pkg, res, parser);
             case TAG_PROTECTED_BROADCAST:
@@ -1514,15 +1517,17 @@
     }
 
     private static ParseResult<ParsingPackage> parseUsesSdk(ParseInput input,
-            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags)
             throws IOException, XmlPullParserException {
         if (SDK_VERSION > 0) {
+            final boolean checkMaxSdkVersion = (flags & PARSE_CHECK_MAX_SDK_VERSION) != 0;
             TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
             try {
                 int minVers = ParsingUtils.DEFAULT_MIN_SDK_VERSION;
                 String minCode = null;
                 int targetVers = ParsingUtils.DEFAULT_TARGET_SDK_VERSION;
                 String targetCode = null;
+                int maxVers = Integer.MAX_VALUE;
 
                 TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion);
                 if (val != null) {
@@ -1550,6 +1555,14 @@
                     targetCode = minCode;
                 }
 
+                if (checkMaxSdkVersion) {
+                    val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_maxSdkVersion);
+                    if (val != null) {
+                        // maxSdkVersion only supports integer
+                        maxVers = val.data;
+                    }
+                }
+
                 ParseResult<Integer> targetSdkVersionResult = FrameworkParsingPackageUtils
                         .computeTargetSdkVersion(targetVers, targetCode, SDK_CODENAMES, input);
                 if (targetSdkVersionResult.isError()) {
@@ -1574,6 +1587,15 @@
 
                 pkg.setMinSdkVersion(minSdkVersion)
                         .setTargetSdkVersion(targetSdkVersion);
+                if (checkMaxSdkVersion) {
+                    ParseResult<Integer> maxSdkVersionResult = FrameworkParsingPackageUtils
+                            .computeMaxSdkVersion(maxVers, SDK_VERSION, input);
+                    if (maxSdkVersionResult.isError()) {
+                        return input.error(maxSdkVersionResult);
+                    }
+                    int maxSdkVersion = maxSdkVersionResult.getResult();
+                    pkg.setMaxSdkVersion(maxSdkVersion);
+                }
 
                 int type;
                 final int innerDepth = parser.getDepth();
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java
index cb474df..0751285 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java
@@ -50,6 +50,7 @@
     public static final String ANDROID_RES_NAMESPACE = "http://schemas.android.com/apk/res/android";
 
     public static final int DEFAULT_MIN_SDK_VERSION = 1;
+    public static final int DEFAULT_MAX_SDK_VERSION = Integer.MAX_VALUE;
     public static final int DEFAULT_TARGET_SDK_VERSION = 0;
 
     public static final int NOT_SET = -1;
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java b/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java
index 3205b76..99bcdb96 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java
@@ -250,6 +250,11 @@
     int getMinSdkVersion();
 
     /**
+     * @see R.styleable#AndroidManifestUsesSdk_maxSdkVersion
+     */
+    int getMaxSdkVersion();
+
+    /**
      * @see ApplicationInfo#getNativeHeapZeroInitialized()
      * @see R.styleable#AndroidManifestApplication_nativeHeapZeroInitialized
      */
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 59b9daf..8087738 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -36,6 +36,7 @@
 import android.app.StatusBarManager;
 import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.EnabledSince;
 import android.content.ComponentName;
 import android.content.Context;
@@ -135,6 +136,17 @@
     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
     private static final long LOCK_DOWN_COLLAPSE_STATUS_BAR = 173031413L;
 
+    /**
+     * In apps targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher, calling
+     * {@link android.service.quicksettings.TileService#requestListeningState} will check that the 
+     * calling package (uid) and the package of the target {@link android.content.ComponentName} 
+     * match. It'll also make sure that the context used can take actions on behalf of the current 
+     * user.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
+    static final long REQUEST_LISTENING_MUST_MATCH_PACKAGE = 172251878L;
+
     private final Context mContext;
 
     private final Handler mHandler = new Handler();
@@ -1652,6 +1664,7 @@
 
     @Override
     public void hideCurrentInputMethodForBubbles() {
+        enforceStatusBarService();
         final long token = Binder.clearCallingIdentity();
         try {
             InputMethodManagerInternal.get().hideCurrentInputMethod(
@@ -1776,6 +1789,42 @@
     }
 
     @Override
+    public void requestTileServiceListeningState(
+            @NonNull ComponentName componentName,
+            int userId
+    ) {
+        int callingUid = Binder.getCallingUid();
+        String packageName = componentName.getPackageName();
+
+        boolean mustPerformChecks = CompatChanges.isChangeEnabled(
+                REQUEST_LISTENING_MUST_MATCH_PACKAGE, callingUid);
+
+        if (mustPerformChecks) {
+            // Check calling user can act on behalf of current user
+            userId = mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), callingUid,
+                    userId, false, ActivityManagerInternal.ALLOW_NON_FULL,
+                    "requestTileServiceListeningState", packageName);
+
+            // Check calling uid matches package
+            checkCallingUidPackage(packageName, callingUid, userId);
+
+            int currentUser = mActivityManagerInternal.getCurrentUserId();
+
+            // Check current user
+            if (userId != currentUser) {
+                throw new IllegalArgumentException("User " + userId + " is not the current user.");
+            }
+        }
+        if (mBar != null) {
+            try {
+                mBar.requestTileServiceListeningState(componentName);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "requestTileServiceListeningState", e);
+            }
+        }
+    }
+
+    @Override
     public void requestAddTile(
             @NonNull ComponentName componentName,
             @NonNull CharSequence label,
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index bd4b8d1..cc1d0e2 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -715,7 +715,7 @@
                     (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
 
             List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
-            if (enabledAgents == null) {
+            if (enabledAgents.isEmpty()) {
                 if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
                         + ": no agents enabled by user");
                 continue;
@@ -1080,9 +1080,7 @@
         }
 
         List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
-        if (previouslyEnabledAgents != null) {
-            discoveredAgents.addAll(previouslyEnabledAgents);
-        }
+        discoveredAgents.addAll(previouslyEnabledAgents);
         utils.setEnabledTrustAgents(discoveredAgents, userId);
         Settings.Secure.putIntForUser(mContext.getContentResolver(),
                 Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 2355333..94fc51d 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3376,11 +3376,17 @@
                 return new ArrayList<>();
             }
         } else {
+            final RecentTasks recentTasks = mWindowManager.mAtmService.getRecentTasks();
+            final int recentsComponentUid = recentTasks != null
+                    ? recentTasks.getRecentsComponentUid()
+                    : -1;
             final ArrayList<ActivityRecord> activities = new ArrayList<>();
-            forAllRootTasks(rootTask -> {
-                if (!dumpVisibleRootTasksOnly || rootTask.shouldBeVisible(null)) {
-                    activities.addAll(rootTask.getDumpActivitiesLocked(name, userId));
+            forAllLeafTasks(task -> {
+                final boolean isRecents = (task.effectiveUid == recentsComponentUid);
+                if (!dumpVisibleRootTasksOnly || task.shouldBeVisible(null) || isRecents) {
+                    activities.addAll(task.getDumpActivitiesLocked(name, userId));
                 }
+                return false;
             });
             return activities;
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 1cf4c1b..5a2f28f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -566,9 +566,14 @@
         try (ZipOutputStream out = new ZipOutputStream(getRawOutputStream())) {
             ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>();
             synchronized (mInternal.mGlobalLock) {
+                final RecentTasks recentTasks = mInternal.mAtmService.getRecentTasks();
+                final int recentsComponentUid = recentTasks != null
+                        ? recentTasks.getRecentsComponentUid()
+                        : -1;
                 // Request dump from all windows parallelly before writing to disk.
                 mInternal.mRoot.forAllWindows(w -> {
-                    if (w.isVisible()) {
+                    final boolean isRecents = (w.getUid() == recentsComponentUid);
+                    if (w.isVisible() || isRecents) {
                         ByteTransferPipe pipe = null;
                         try {
                             pipe = new ByteTransferPipe();
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 1c6a3b5..0cd9494 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -106,7 +106,6 @@
     register_android_server_HardwarePropertiesManagerService(env);
     register_android_server_storage_AppFuse(env);
     register_android_server_SyntheticPasswordManager(env);
-    register_android_graphics_GraphicsStatsService(env);
     register_android_hardware_display_DisplayViewport(env);
     register_android_server_am_CachedAppOptimizer(env);
     register_android_server_am_LowMemDetector(env);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c8eaa23..f7c66c5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -293,8 +293,6 @@
             "com.android.server.wifi.p2p.WifiP2pService";
     private static final String LOWPAN_SERVICE_CLASS =
             "com.android.server.lowpan.LowpanService";
-    private static final String ETHERNET_SERVICE_CLASS =
-            "com.android.server.ethernet.EthernetService";
     private static final String JOB_SCHEDULER_SERVICE_CLASS =
             "com.android.server.job.JobSchedulerService";
     private static final String LOCK_SETTINGS_SERVICE_CLASS =
@@ -1995,13 +1993,6 @@
                 t.traceEnd();
             }
 
-            if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
-                    mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
-                t.traceBegin("StartEthernet");
-                mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
-                t.traceEnd();
-            }
-
             t.traceBegin("StartPacProxyService");
             try {
                 pacProxyService = new PacProxyService(context);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
index 1515282..97b52a9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
@@ -24,7 +24,6 @@
 import android.os.storage.StorageManager
 import android.util.ArrayMap
 import android.util.PackageUtils
-import com.android.internal.util.FunctionalUtils
 import com.android.server.SystemConfig.SharedLibraryEntry
 import com.android.server.compat.PlatformCompat
 import com.android.server.extendedtestutils.wheneverStatic
@@ -35,7 +34,6 @@
 import com.android.server.testutils.any
 import com.android.server.testutils.eq
 import com.android.server.testutils.mock
-import com.android.server.testutils.mockThrowOnUnmocked
 import com.android.server.testutils.nullable
 import com.android.server.testutils.spy
 import com.android.server.testutils.whenever
@@ -59,6 +57,7 @@
 import kotlin.test.assertFalse
 import kotlin.test.assertTrue
 
+@Ignore("b/216603387")
 @RunWith(JUnit4::class)
 class SharedLibrariesImplTest {
 
@@ -249,7 +248,6 @@
         assertThat(testPackageSetting.usesLibraryFiles).contains(builtinLibPath(BUILTIN_LIB_NAME))
     }
 
-    @Ignore("b/216603387")
     @Test
     fun updateSharedLibraries_withStaticLibPackage() {
         val testPackageSetting = mExistingSettings[STATIC_LIB_PACKAGE_NAME]!!
@@ -262,7 +260,6 @@
         assertThat(testPackageSetting.usesLibraryFiles).contains(apkPath(DYNAMIC_LIB_PACKAGE_NAME))
     }
 
-    @Ignore("b/216603387")
     @Test
     fun updateSharedLibraries_withConsumerPackage() {
         val testPackageSetting = mExistingSettings[CONSUMER_PACKAGE_NAME]!!
@@ -276,7 +273,6 @@
         assertThat(testPackageSetting.usesLibraryFiles).contains(apkPath(STATIC_LIB_PACKAGE_NAME))
     }
 
-    @Ignore("b/216603387")
     @Test
     fun updateAllSharedLibraries() {
         mExistingSettings.forEach {
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 4de15c8..928c76d 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -330,11 +330,12 @@
 
     @Test
     public void testPriorityPersisted() throws Exception {
-        final JobInfo.Builder b = new Builder(92, mComponent)
+        final JobInfo job = new Builder(92, mComponent)
                 .setOverrideDeadline(5000)
                 .setPriority(JobInfo.PRIORITY_MIN)
-                .setPersisted(true);
-        final JobStatus js = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null);
+                .setPersisted(true)
+                .build();
+        final JobStatus js = JobStatus.createFromJobInfo(job, SOME_UID, null, -1, null);
         mTaskStoreUnderTest.add(js);
         waitForPendingIo();
 
@@ -342,7 +343,7 @@
         mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true);
         final JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
         assertEquals("Priority not correctly persisted.",
-                JobInfo.PRIORITY_MIN, loaded.getEffectivePriority());
+                JobInfo.PRIORITY_MIN, job.getPriority());
     }
 
     /**
diff --git a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java
index 1442f1c..d76a1de 100644
--- a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java
@@ -23,9 +23,11 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.argThat;
 import static org.mockito.Mockito.eq;
@@ -37,6 +39,7 @@
 import android.Manifest;
 import android.app.ActivityManagerInternal;
 import android.app.StatusBarManager;
+import android.compat.testing.PlatformCompatChangeRule;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.om.IOverlayManager;
@@ -62,10 +65,13 @@
 import com.android.server.policy.GlobalActionsProvider;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
+import libcore.junit.util.compat.CoreCompatChangeRule;
+
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 import org.mockito.ArgumentCaptor;
@@ -73,6 +79,7 @@
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
 
 @RunWith(JUnit4.class)
 public class StatusBarManagerServiceTest {
@@ -88,6 +95,9 @@
     public final TestableContext mContext =
             new NoBroadcastContextWrapper(InstrumentationRegistry.getContext());
 
+    @Rule
+    public TestRule mCompatChangeRule = new PlatformCompatChangeRule();
+
     @Mock
     private ActivityTaskManagerInternal mActivityTaskManagerInternal;
     @Mock
@@ -127,6 +137,7 @@
 
         when(mMockStatusBar.asBinder()).thenReturn(mMockStatusBar);
         when(mApplicationInfo.loadLabel(any())).thenReturn(APP_NAME);
+        mockHandleIncomingUser();
 
         mStatusBarManagerService = new StatusBarManagerService(mContext);
         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
@@ -142,6 +153,80 @@
     }
 
     @Test
+    @CoreCompatChangeRule.EnableCompatChanges(
+            {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE})
+    public void testRequestActive_changeEnabled_OKCall() throws RemoteException {
+        int user = 0;
+        mockEverything(user);
+        mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user);
+
+        verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT);
+    }
+
+    @Test
+    @CoreCompatChangeRule.EnableCompatChanges(
+            {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE})
+    public void testRequestActive_changeEnabled_differentPackage_fail() throws RemoteException {
+        when(mPackageManagerInternal.getPackageUid(TEST_PACKAGE, 0L, mContext.getUserId()))
+                .thenReturn(Binder.getCallingUid() + 1);
+        try {
+            mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, 0);
+            fail("Should cause security exception");
+        } catch (SecurityException e) { }
+        verify(mMockStatusBar, never()).requestTileServiceListeningState(TEST_COMPONENT);
+    }
+
+    @Test
+    @CoreCompatChangeRule.EnableCompatChanges(
+            {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE})
+    public void testRequestActive_changeEnabled_notCurrentUser_fail() throws RemoteException {
+        mockUidCheck();
+        int user = 0;
+        mockCurrentUserCheck(user);
+        try {
+            mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user + 1);
+            fail("Should cause illegal argument exception");
+        } catch (IllegalArgumentException e) { }
+
+        // Do not call into SystemUI
+        verify(mMockStatusBar, never()).requestTileServiceListeningState(TEST_COMPONENT);
+    }
+
+    @Test
+    @CoreCompatChangeRule.DisableCompatChanges(
+            {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE})
+    public void testRequestActive_changeDisabled_pass() throws RemoteException {
+        int user = 0;
+        mockEverything(user);
+        mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user);
+
+        verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT);
+    }
+
+    @Test
+    @CoreCompatChangeRule.DisableCompatChanges(
+            {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE})
+    public void testRequestActive_changeDisabled_differentPackage_pass() throws RemoteException {
+        when(mPackageManagerInternal.getPackageUid(TEST_PACKAGE, 0L, mContext.getUserId()))
+                .thenReturn(Binder.getCallingUid() + 1);
+        mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, 0);
+
+        verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT);
+    }
+
+    @Test
+    @CoreCompatChangeRule.DisableCompatChanges(
+            {StatusBarManagerService.REQUEST_LISTENING_MUST_MATCH_PACKAGE})
+    public void testRequestActive_changeDisabled_notCurrentUser_pass() throws RemoteException {
+        mockUidCheck();
+        int user = 0;
+        mockCurrentUserCheck(user);
+        mStatusBarManagerService.requestTileServiceListeningState(TEST_COMPONENT, user + 1);
+
+        verify(mMockStatusBar).requestTileServiceListeningState(TEST_COMPONENT);
+    }
+
+    @Test
     public void testHandleIncomingUserCalled() {
         int fakeUser = 17;
         try {
@@ -252,7 +337,7 @@
         mockCurrentUserCheck(user);
         IntentMatcher im = new IntentMatcher(
                 new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT));
-        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0),
+        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L),
                 eq(user), anyInt())).thenReturn(null);
 
         Callback callback = new Callback();
@@ -272,7 +357,7 @@
 
         IntentMatcher im = new IntentMatcher(
                 new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT));
-        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0),
+        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L),
                 eq(user), anyInt())).thenReturn(r);
         when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT,
                 Binder.getCallingUid(), user)).thenReturn(
@@ -294,7 +379,7 @@
 
         IntentMatcher im = new IntentMatcher(
                 new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT));
-        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0),
+        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L),
                 eq(user), anyInt())).thenReturn(r);
         when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT,
                 Binder.getCallingUid(), user)).thenReturn(
@@ -318,7 +403,7 @@
 
         IntentMatcher im = new IntentMatcher(
                 new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT));
-        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0),
+        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L),
                 eq(user), anyInt())).thenReturn(r);
         when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT,
                 Binder.getCallingUid(), user)).thenReturn(
@@ -342,7 +427,7 @@
 
         IntentMatcher im = new IntentMatcher(
                 new Intent(TileService.ACTION_QS_TILE).setComponent(TEST_COMPONENT));
-        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0),
+        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L),
                 eq(user), anyInt())).thenReturn(r);
         when(mPackageManagerInternal.getComponentEnabledSetting(TEST_COMPONENT,
                 Binder.getCallingUid(), user)).thenReturn(
@@ -641,7 +726,7 @@
     }
 
     private void mockUidCheck(String packageName) {
-        when(mPackageManagerInternal.getPackageUid(eq(packageName), anyInt(), anyInt()))
+        when(mPackageManagerInternal.getPackageUid(eq(packageName), anyLong(), anyInt()))
                 .thenReturn(Binder.getCallingUid());
     }
 
@@ -667,7 +752,7 @@
 
         IntentMatcher im = new IntentMatcher(
                 new Intent(TileService.ACTION_QS_TILE).setComponent(componentName));
-        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0),
+        when(mPackageManagerInternal.resolveService(argThat(im), nullable(String.class), eq(0L),
                 eq(user), anyInt())).thenReturn(r);
         when(mPackageManagerInternal.getComponentEnabledSetting(componentName,
                 Binder.getCallingUid(), user)).thenReturn(
@@ -679,6 +764,15 @@
                 PROCESS_STATE_TOP);
     }
 
+    private void mockHandleIncomingUser() {
+        when(mActivityManagerInternal.handleIncomingUser(anyInt(), anyInt(), anyInt(), anyBoolean(),
+                anyInt(), anyString(), anyString())).thenAnswer(
+                    (Answer<Integer>) invocation -> {
+                        return invocation.getArgument(2); // same user
+                    }
+        );
+    }
+
     private void mockEverything(int user) {
         mockUidCheck();
         mockCurrentUserCheck(user);
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 1ce957d..210d2fa 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -62,7 +62,10 @@
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.intThat;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -76,11 +79,13 @@
 import android.appwidget.AppWidgetManager;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
 import android.hardware.display.DisplayManager;
 import android.os.Handler;
 import android.os.Looper;
@@ -118,6 +123,7 @@
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * Unit test for AppStandbyController.
@@ -421,8 +427,31 @@
         pib.packageName = PACKAGE_BACKGROUND_LOCATION;
         packages.add(pib);
 
-        doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt());
 
+        // Set up getInstalledPackagesAsUser().
+        doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(),
+                anyInt());
+
+        // Set up getInstalledPackagesAsUser() for "MATCH_ONLY_SYSTEM"
+        doReturn(
+                packages.stream().filter(pinfo -> pinfo.applicationInfo.isSystemApp())
+                .collect(Collectors.toList())
+        ).when(mockPm).getInstalledPackagesAsUser(
+                intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0),
+                anyInt());
+
+        // Set up queryIntentActivitiesAsUser()
+        final ArrayList<ResolveInfo> systemFrontDoorActivities = new ArrayList<>();
+        final ResolveInfo frontDoorActivity = new ResolveInfo();
+        frontDoorActivity.activityInfo = new ActivityInfo();
+        frontDoorActivity.activityInfo.packageName = pis.packageName;
+        systemFrontDoorActivities.add(frontDoorActivity);
+        doReturn(systemFrontDoorActivities).when(mockPm)
+                .queryIntentActivitiesAsUser(any(Intent.class),
+                intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0),
+                anyInt());
+
+        // Set up other APIs.
         try {
             for (int i = 0; i < packages.size(); ++i) {
                 PackageInfo pkg = packages.get(i);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
index 50151bf..46b47f4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
@@ -88,7 +88,7 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mPermissionHelper = new PermissionHelper(mPmi, mPackageManager, mPermManager, true);
+        mPermissionHelper = new PermissionHelper(mPmi, mPackageManager, mPermManager, true, false);
         PackageInfo testPkgInfo = new PackageInfo();
         testPkgInfo.requestedPermissions = new String[]{ Manifest.permission.POST_NOTIFICATIONS };
         when(mPackageManager.getPackageInfo(anyString(), anyLong(), anyInt()))
@@ -100,7 +100,7 @@
     public void testMethodsThrowIfMigrationDisabled() throws IllegalAccessException,
             InvocationTargetException {
         PermissionHelper permHelper =
-                new PermissionHelper(mPmi, mPackageManager, mPermManager, false);
+                new PermissionHelper(mPmi, mPackageManager, mPermManager, false, false);
 
         Method[] allMethods = PermissionHelper.class.getDeclaredMethods();
         for (Method method : allMethods) {
@@ -302,6 +302,26 @@
     }
 
     @Test
+    public void testSetNotificationPermission_pkgPerm_grantedByDefaultPermSet_allUserSet()
+            throws Exception {
+        mPermissionHelper = new PermissionHelper(mPmi, mPackageManager, mPermManager, true, true);
+        when(mPmi.checkPermission(anyString(), anyString(), anyInt()))
+                .thenReturn(PERMISSION_DENIED);
+        when(mPermManager.getPermissionFlags(anyString(),
+                eq(Manifest.permission.POST_NOTIFICATIONS),
+                anyInt())).thenReturn(FLAG_PERMISSION_GRANTED_BY_DEFAULT);
+        PermissionHelper.PackagePermission pkgPerm = new PermissionHelper.PackagePermission(
+                "pkg", 10, true, false);
+
+        mPermissionHelper.setNotificationPermission(pkgPerm);
+        verify(mPermManager).grantRuntimePermission(
+                "pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
+        verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
+                FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_REVIEW_REQUIRED,
+                FLAG_PERMISSION_USER_SET, true, 10);
+    }
+
+    @Test
     public void testSetNotificationPermission_revokeUserSet() throws Exception {
         when(mPmi.checkPermission(anyString(), anyString(), anyInt()))
                 .thenReturn(PERMISSION_GRANTED);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 1eb391d..5ef22de 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -16790,7 +16790,10 @@
      * Callback to listen for when the set of packages with carrier privileges for a SIM changes.
      *
      * @hide
+     * @deprecated Use {@link CarrierPrivilegesCallback} instead. This API will be removed soon
+     * prior to API finalization.
      */
+    @Deprecated
     @SystemApi
     public interface CarrierPrivilegesListener {
         /**
@@ -16810,6 +16813,54 @@
     }
 
     /**
+     * Callbacks to listen for when the set of packages with carrier privileges for a SIM changes.
+     *
+     * <p>Of note, when multiple callbacks are registered, they may be triggered one after another.
+     * The ordering of them is not guaranteed and thus should not be depend on.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface CarrierPrivilegesCallback {
+        /**
+         * Called when the set of packages with carrier privileges has changed.
+         *
+         * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
+         * switch and the same set of packages remains privileged after the switch.
+         *
+         * <p>At registration, the callback will receive the current set of privileged packages.
+         *
+         * @param privilegedPackageNames The updated set of package names that have carrier
+         *                               privileges
+         * @param privilegedUids         The updated set of UIDs that have carrier privileges
+         */
+        void onCarrierPrivilegesChanged(
+                @NonNull Set<String> privilegedPackageNames, @NonNull Set<Integer> privilegedUids);
+
+        /**
+         * Called when the {@link CarrierService} for the current user profile has changed.
+         *
+         * <p>This method does nothing by default. Clients that are interested in the carrier
+         * service change should override this method to get package name and UID info.
+         *
+         * <p>At registration, the callback will receive the current carrier service info.
+         *
+         * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
+         * switch and the same carrier service remains after switch.
+         *
+         * @param carrierServicePackageName package name of the {@link CarrierService}. May be
+         *                                  {@code null} when no carrier service is detected.
+         * @param carrierServiceUid         UID of the {@link CarrierService}. May be
+         *                                  {@link android.os.Process#INVALID_UID} if no carrier
+         *                                  service is detected.
+         */
+        default void onCarrierServiceChanged(
+                @Nullable String carrierServicePackageName, int carrierServiceUid) {
+            // do nothing by default
+        }
+    }
+
+    /**
      * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
      * receive callbacks when the set of packages with carrier privileges changes. The callback will
      * immediately be called with the latest state.
@@ -16818,7 +16869,10 @@
      * @param executor The executor where {@code listener} will be invoked
      * @param listener The callback to register
      * @hide
+     * @deprecated Use {@link #unregisterCarrierPrivilegesCallback} instead. This API will be
+     * removed prior to API finalization.
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void addCarrierPrivilegesListener(
@@ -16842,7 +16896,10 @@
      * Unregisters an existing {@link CarrierPrivilegesListener}.
      *
      * @hide
+     * @deprecated Use {@link #unregisterCarrierPrivilegesCallback} instead. This API will be
+     * removed prior to API finalization.
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
@@ -16890,4 +16947,53 @@
             ex.rethrowAsRuntimeException();
         }
     }
+
+    /**
+     * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to
+     * receive callbacks when the set of packages with carrier privileges changes. The callback will
+     * immediately be called with the latest state.
+     *
+     * @param logicalSlotIndex The SIM slot to listen on
+     * @param executor The executor where {@code callback} will be invoked
+     * @param callback The callback to register
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void registerCarrierPrivilegesCallback(
+            int logicalSlotIndex,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull CarrierPrivilegesCallback callback) {
+        if (mContext == null) {
+            throw new IllegalStateException("Telephony service is null");
+        } else if (executor == null || callback == null) {
+            throw new IllegalArgumentException(
+                    "CarrierPrivilegesCallback and executor must be non-null");
+        }
+        mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
+        if (mTelephonyRegistryMgr == null) {
+            throw new IllegalStateException("Telephony registry service is null");
+        }
+        mTelephonyRegistryMgr.addCarrierPrivilegesCallback(logicalSlotIndex, executor, callback);
+    }
+
+    /**
+     * Unregisters an existing {@link CarrierPrivilegesCallback}.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void unregisterCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) {
+        if (mContext == null) {
+            throw new IllegalStateException("Telephony service is null");
+        } else if (callback == null) {
+            throw new IllegalArgumentException("CarrierPrivilegesCallback must be non-null");
+        }
+        mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
+        if (mTelephonyRegistryMgr == null) {
+            throw new IllegalStateException("Telephony registry service is null");
+        }
+        mTelephonyRegistryMgr.removeCarrierPrivilegesCallback(callback);
+    }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index b0e53e9..c3a4769 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -74,7 +74,7 @@
      * Checks that the nav bar layer starts invisible, becomes visible during unlocking animation
      * and remains visible at the end
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun navBarLayerVisibilityChanges() {
         testSpec.assertLayers {
diff --git a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
index 8630ec4..d85a5bd 100644
--- a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
+++ b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
@@ -967,16 +967,16 @@
      *
      * @param ifaceName Name of the interface.
      */
-    public int getMaxNumScanSsids(@NonNull String ifaceName) {
+    public int getMaxSsidsPerScan(@NonNull String ifaceName) {
         IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
         if (scannerImpl == null) {
             Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
             return 0;
         }
         try {
-            return scannerImpl.getMaxNumScanSsids();
+            return scannerImpl.getMaxSsidsPerScan();
         } catch (RemoteException e1) {
-            Log.e(TAG, "Failed to getMaxNumScanSsids");
+            Log.e(TAG, "Failed to getMaxSsidsPerScan");
         }
         return 0;
     }