Merge "Restrict DisplayArea appBounds to the override bounds" into sc-dev
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index cdf5df6c..30ed7de 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -8,6 +8,7 @@
                cmds/input/
                cmds/uinput/
                core/jni/
+               libs/hwui/
                libs/input/
                native/
                services/core/jni/
diff --git a/core/api/current.txt b/core/api/current.txt
index 73386a7..d1b9716 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8350,6 +8350,7 @@
     method public android.appwidget.AppWidgetProviderInfo clone();
     method public int describeContents();
     method public final android.os.UserHandle getProfile();
+    method @NonNull public android.content.pm.ActivityInfo getProviderInfo();
     method @Nullable public final String loadDescription(@NonNull android.content.Context);
     method public final android.graphics.drawable.Drawable loadIcon(@NonNull android.content.Context, int);
     method public final String loadLabel(android.content.pm.PackageManager);
@@ -11868,6 +11869,7 @@
   }
 
   public class LauncherActivityInfo {
+    method @NonNull public android.content.pm.ActivityInfo getActivityInfo();
     method public android.content.pm.ApplicationInfo getApplicationInfo();
     method public android.graphics.drawable.Drawable getBadgedIcon(int);
     method public android.content.ComponentName getComponentName();
@@ -12240,6 +12242,7 @@
     method @NonNull public abstract android.content.pm.ActivityInfo getReceiverInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.content.res.Resources getResourcesForActivity(@NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.content.res.Resources getResourcesForApplication(@NonNull android.content.pm.ApplicationInfo) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull public android.content.res.Resources getResourcesForApplication(@NonNull android.content.pm.ApplicationInfo, @Nullable android.content.res.Configuration) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.content.res.Resources getResourcesForApplication(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.content.pm.ServiceInfo getServiceInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
@@ -16800,6 +16803,18 @@
 
 package android.hardware {
 
+  public abstract class Battery {
+    ctor public Battery();
+    method @FloatRange(from=-1.0F, to=1.0f) public abstract float getCapacity();
+    method public abstract int getStatus();
+    method public abstract boolean hasBattery();
+    field public static final int STATUS_CHARGING = 2; // 0x2
+    field public static final int STATUS_DISCHARGING = 3; // 0x3
+    field public static final int STATUS_FULL = 5; // 0x5
+    field public static final int STATUS_NOT_CHARGING = 4; // 0x4
+    field public static final int STATUS_UNKNOWN = 1; // 0x1
+  }
+
   @Deprecated public class Camera {
     method @Deprecated public final void addCallbackBuffer(byte[]);
     method @Deprecated public final void autoFocus(android.hardware.Camera.AutoFocusCallback);
@@ -46360,6 +46375,7 @@
 
   public final class InputDevice implements android.os.Parcelable {
     method public int describeContents();
+    method @NonNull public android.hardware.Battery getBattery();
     method public int getControllerNumber();
     method public String getDescriptor();
     method public static android.view.InputDevice getDevice(int);
@@ -46414,6 +46430,7 @@
     field public static final int SOURCE_MOUSE = 8194; // 0x2002
     field public static final int SOURCE_MOUSE_RELATIVE = 131076; // 0x20004
     field public static final int SOURCE_ROTARY_ENCODER = 4194304; // 0x400000
+    field public static final int SOURCE_SENSOR = 67108864; // 0x4000000
     field public static final int SOURCE_STYLUS = 16386; // 0x4002
     field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
     field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 0f49dc5..e8650fa 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -157,6 +157,10 @@
 
 package android.net {
 
+  public final class ConnectivityFrameworkInitializer {
+    method public static void registerServiceWrappers();
+  }
+
   public class ConnectivityManager {
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e00e739..b4cc89e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3183,6 +3183,7 @@
 
   public class ContextHubClientCallback {
     ctor public ContextHubClientCallback();
+    method public void onClientAuthorizationChanged(@NonNull android.hardware.location.ContextHubClient, long, int);
     method public void onHubReset(android.hardware.location.ContextHubClient);
     method public void onMessageFromNanoApp(android.hardware.location.ContextHubClient, android.hardware.location.NanoAppMessage);
     method public void onNanoAppAborted(android.hardware.location.ContextHubClient, long, int);
@@ -3219,6 +3220,7 @@
 
   public class ContextHubIntentEvent {
     method @NonNull public static android.hardware.location.ContextHubIntentEvent fromIntent(@NonNull android.content.Intent);
+    method public int getClientAuthorizationState();
     method @NonNull public android.hardware.location.ContextHubInfo getContextHubInfo();
     method public int getEventType();
     method public int getNanoAppAbortCode();
@@ -3227,8 +3229,10 @@
   }
 
   public final class ContextHubManager {
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@Nullable android.content.Context, @NonNull android.hardware.location.ContextHubInfo, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.location.ContextHubClientCallback);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@Nullable android.content.Context, @NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
@@ -3246,6 +3250,10 @@
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public int unloadNanoApp(int);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
     method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback);
+    field public static final int AUTHORIZATION_DENIED = 0; // 0x0
+    field public static final int AUTHORIZATION_DENIED_GRACE_PERIOD = 1; // 0x1
+    field public static final int AUTHORIZATION_GRANTED = 2; // 0x2
+    field public static final int EVENT_CLIENT_AUTHORIZATION = 7; // 0x7
     field public static final int EVENT_HUB_RESET = 6; // 0x6
     field public static final int EVENT_NANOAPP_ABORTED = 4; // 0x4
     field public static final int EVENT_NANOAPP_DISABLED = 3; // 0x3
@@ -3253,6 +3261,7 @@
     field public static final int EVENT_NANOAPP_LOADED = 0; // 0x0
     field public static final int EVENT_NANOAPP_MESSAGE = 5; // 0x5
     field public static final int EVENT_NANOAPP_UNLOADED = 1; // 0x1
+    field public static final String EXTRA_CLIENT_AUTHORIZATION_STATE = "android.hardware.location.extra.CLIENT_AUTHORIZATION_STATE";
     field public static final String EXTRA_CONTEXT_HUB_INFO = "android.hardware.location.extra.CONTEXT_HUB_INFO";
     field public static final String EXTRA_EVENT_TYPE = "android.hardware.location.extra.EVENT_TYPE";
     field public static final String EXTRA_MESSAGE = "android.hardware.location.extra.MESSAGE";
@@ -3491,8 +3500,10 @@
 
   public final class NanoAppState implements android.os.Parcelable {
     ctor public NanoAppState(long, int, boolean);
+    ctor public NanoAppState(long, int, boolean, @NonNull java.util.List<java.lang.String>);
     method public int describeContents();
     method public long getNanoAppId();
+    method @NonNull public java.util.List<java.lang.String> getNanoAppPermissions();
     method public long getNanoAppVersion();
     method public boolean isEnabled();
     method public void writeToParcel(android.os.Parcel, int);
@@ -5817,6 +5828,7 @@
 
   public final class RestartEvent extends android.media.tv.tuner.filter.FilterEvent {
     method public int getStartId();
+    field public static final int NEW_FILTER_FIRST_START_ID = 0; // 0x0
   }
 
   public final class ScramblingStatusEvent extends android.media.tv.tuner.filter.FilterEvent {
@@ -9850,6 +9862,7 @@
     method public void onNotificationDirectReplied(@NonNull String);
     method @Nullable public abstract android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification);
     method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel);
+    method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel, @NonNull android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean);
     method public abstract void onNotificationSnoozedUntilContext(@NonNull android.service.notification.StatusBarNotification, @NonNull String);
     method public void onNotificationVisibilityChanged(@NonNull String, boolean);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9b141b7..1f9cb64 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2291,9 +2291,10 @@
      * Resources if one has already been created.
      */
     Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
-            String[] libDirs, LoadedApk pkgInfo) {
+            String[] libDirs, LoadedApk pkgInfo, Configuration overrideConfig) {
         return mResourcesManager.getResources(null, resDir, splitResDirs, overlayDirs, libDirs,
-                null, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader(), null);
+                null, overrideConfig, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader(),
+                null);
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index d716a3c..7410a1c 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -50,7 +50,7 @@
  *
  * <p>
  * Application process could die for many reasons, for example {@link #REASON_LOW_MEMORY}
- * when it was killed by the ystem because it was running low on memory. Reason
+ * when it was killed by the system because it was running low on memory. Reason
  * of the death can be retrieved via {@link #getReason}. Besides the reason, there are a few other
  * auxiliary APIs like {@link #getStatus} and {@link #getImportance} to help the caller with
  * additional diagnostic information.
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 77542bd..7e7f887 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -70,6 +70,7 @@
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VersionedPackage;
 import android.content.pm.dex.ArtManager;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
@@ -1691,20 +1692,29 @@
     @Override
     public Resources getResourcesForApplication(@NonNull ApplicationInfo app)
             throws NameNotFoundException {
+        return getResourcesForApplication(app, null);
+    }
+
+    @Override
+    public Resources getResourcesForApplication(@NonNull ApplicationInfo app,
+            @Nullable Configuration configuration) throws NameNotFoundException {
         if (app.packageName.equals("system")) {
-            return mContext.mMainThread.getSystemUiContext().getResources();
+            Context sysuiContext = mContext.mMainThread.getSystemUiContext();
+            if (configuration != null) {
+                sysuiContext = sysuiContext.createConfigurationContext(configuration);
+            }
+            return sysuiContext.getResources();
         }
         final boolean sameUid = (app.uid == Process.myUid());
         final Resources r = mContext.mMainThread.getTopLevelResources(
-                    sameUid ? app.sourceDir : app.publicSourceDir,
-                    sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
-                    app.resourceDirs, app.sharedLibraryFiles,
-                    mContext.mPackageInfo);
+                sameUid ? app.sourceDir : app.publicSourceDir,
+                sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
+                app.resourceDirs, app.sharedLibraryFiles,
+                mContext.mPackageInfo, configuration);
         if (r != null) {
             return r;
         }
         throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
-
     }
 
     @Override
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 1498dae7..7ff1d97 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -120,21 +120,16 @@
 import android.media.tv.TvInputManager;
 import android.media.tv.tunerresourcemanager.ITunerResourceManager;
 import android.media.tv.tunerresourcemanager.TunerResourceManager;
-import android.net.ConnectivityDiagnosticsManager;
-import android.net.ConnectivityManager;
+import android.net.ConnectivityFrameworkInitializer;
 import android.net.EthernetManager;
-import android.net.IConnectivityManager;
 import android.net.IEthernetManager;
 import android.net.IIpSecService;
 import android.net.INetworkPolicyManager;
-import android.net.ITestNetworkManager;
 import android.net.IpSecManager;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkScoreManager;
 import android.net.NetworkWatchlistManager;
-import android.net.TestNetworkManager;
 import android.net.TetheringManager;
-import android.net.VpnManager;
 import android.net.lowpan.ILowpanManager;
 import android.net.lowpan.LowpanManager;
 import android.net.nsd.INsdManager;
@@ -163,7 +158,6 @@
 import android.os.IncidentManager;
 import android.os.PowerManager;
 import android.os.RecoverySystem;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.StatsFrameworkInitializer;
@@ -370,15 +364,6 @@
         // (which extends it).
         SYSTEM_SERVICE_NAMES.put(android.text.ClipboardManager.class, Context.CLIPBOARD_SERVICE);
 
-        registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
-                new StaticApplicationContextServiceFetcher<ConnectivityManager>() {
-            @Override
-            public ConnectivityManager createService(Context context) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE);
-                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
-                return new ConnectivityManager(context, service);
-            }});
-
         registerService(Context.NETD_SERVICE, IBinder.class, new StaticServiceFetcher<IBinder>() {
             @Override
             public IBinder createService() throws ServiceNotFoundException {
@@ -412,50 +397,6 @@
                 return new IpSecManager(ctx, service);
             }});
 
-        registerService(Context.VPN_MANAGEMENT_SERVICE, VpnManager.class,
-                new CachedServiceFetcher<VpnManager>() {
-            @Override
-            public VpnManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
-                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
-                return new VpnManager(ctx, service);
-            }});
-
-        registerService(Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
-                ConnectivityDiagnosticsManager.class,
-                new CachedServiceFetcher<ConnectivityDiagnosticsManager>() {
-            @Override
-            public ConnectivityDiagnosticsManager createService(ContextImpl ctx)
-                    throws ServiceNotFoundException {
-                // ConnectivityDiagnosticsManager is backed by ConnectivityService
-                IBinder b = ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE);
-                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
-                return new ConnectivityDiagnosticsManager(ctx, service);
-            }});
-
-        registerService(
-                Context.TEST_NETWORK_SERVICE,
-                TestNetworkManager.class,
-                new StaticApplicationContextServiceFetcher<TestNetworkManager>() {
-                    @Override
-                    public TestNetworkManager createService(Context context)
-                            throws ServiceNotFoundException {
-                        IBinder csBinder =
-                                ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE);
-                        IConnectivityManager csMgr =
-                                IConnectivityManager.Stub.asInterface(csBinder);
-
-                        final IBinder tnBinder;
-                        try {
-                            tnBinder = csMgr.startOrGetTestNetworkService();
-                        } catch (RemoteException e) {
-                            throw new ServiceNotFoundException(Context.TEST_NETWORK_SERVICE);
-                        }
-                        ITestNetworkManager tnMgr = ITestNetworkManager.Stub.asInterface(tnBinder);
-                        return new TestNetworkManager(tnMgr);
-                    }
-                });
-
         registerService(Context.COUNTRY_DETECTOR, CountryDetector.class,
                 new StaticServiceFetcher<CountryDetector>() {
             @Override
@@ -1441,6 +1382,7 @@
         try {
             // Note: the following functions need to be @SystemApis, once they become mainline
             // modules.
+            ConnectivityFrameworkInitializer.registerServiceWrappers();
             JobSchedulerFrameworkInitializer.registerServiceWrappers();
             BlobStoreManagerFrameworkInitializer.initialize();
             TelephonyFrameworkInitializer.registerServiceWrappers();
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 93d96d0..e96e22c4 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -406,6 +406,14 @@
         return new UserHandle(UserHandle.getUserId(providerInfo.applicationInfo.uid));
     }
 
+    /**
+     * Returns the broadcast receiver that is providing this widget.
+     */
+    @NonNull
+    public ActivityInfo getProviderInfo() {
+        return providerInfo;
+    }
+
     @Override
     @SuppressWarnings("deprecation")
     public void writeToParcel(Parcel out, int flags) {
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 82d7b63..16e720e 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.annotation.FloatRange;
+import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -32,8 +33,6 @@
  * and badged icon for the activity.
  */
 public class LauncherActivityInfo {
-    private static final String TAG = "LauncherActivityInfo";
-
     private final PackageManager mPm;
     private UserHandle mUser;
     private final LauncherActivityInfoInternal mInternal;
@@ -81,7 +80,7 @@
      */
     public CharSequence getLabel() {
         // TODO: Go through LauncherAppsService
-        return mInternal.getActivityInfo().loadLabel(mPm);
+        return getActivityInfo().loadLabel(mPm);
     }
 
     /**
@@ -101,20 +100,20 @@
      */
     public Drawable getIcon(int density) {
         // TODO: Go through LauncherAppsService
-        final int iconRes = mInternal.getActivityInfo().getIconResource();
+        final int iconRes = getActivityInfo().getIconResource();
         Drawable icon = null;
         // Get the preferred density icon from the app's resources
         if (density != 0 && iconRes != 0) {
             try {
                 final Resources resources = mPm.getResourcesForApplication(
-                        mInternal.getActivityInfo().applicationInfo);
+                        getActivityInfo().applicationInfo);
                 icon = resources.getDrawableForDensity(iconRes, density);
             } catch (NameNotFoundException | Resources.NotFoundException exc) {
             }
         }
         // Get the default density icon
         if (icon == null) {
-            icon = mInternal.getActivityInfo().loadIcon(mPm);
+            icon = getActivityInfo().loadIcon(mPm);
         }
         return icon;
     }
@@ -126,25 +125,25 @@
      * @hide remove before shipping
      */
     public int getApplicationFlags() {
-        return mInternal.getActivityInfo().flags;
+        return getActivityInfo().flags;
     }
 
     /**
      * Returns the ActivityInfo of the activity.
      *
      * @return Activity Info
-     * @hide
      */
+    @NonNull
     public ActivityInfo getActivityInfo() {
         return mInternal.getActivityInfo();
     }
 
     /**
-     * Returns the application info for the appliction this activity belongs to.
+     * Returns the application info for the application this activity belongs to.
      * @return
      */
     public ApplicationInfo getApplicationInfo() {
-        return mInternal.getActivityInfo().applicationInfo;
+        return getActivityInfo().applicationInfo;
     }
 
     /**
@@ -155,7 +154,7 @@
     public long getFirstInstallTime() {
         try {
             // TODO: Go through LauncherAppsService
-            return mPm.getPackageInfo(mInternal.getActivityInfo().packageName,
+            return mPm.getPackageInfo(getActivityInfo().packageName,
                     PackageManager.MATCH_UNINSTALLED_PACKAGES).firstInstallTime;
         } catch (NameNotFoundException nnfe) {
             // Sorry, can't find package
@@ -164,11 +163,11 @@
     }
 
     /**
-     * Returns the name for the acitivty from  android:name in the manifest.
-     * @return the name from android:name for the acitivity.
+     * Returns the name for the activity from  android:name in the manifest.
+     * @return the name from android:name for the activity.
      */
     public String getName() {
-        return mInternal.getActivityInfo().name;
+        return getActivityInfo().name;
     }
 
     /**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 9ae9c25..9085ed2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -54,6 +54,7 @@
 import android.content.pm.parsing.result.ParseInput;
 import android.content.pm.parsing.result.ParseResult;
 import android.content.pm.parsing.result.ParseTypeImpl;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Rect;
@@ -6703,6 +6704,22 @@
             throws NameNotFoundException;
 
     /**
+     * Retrieve the resources for an application for the provided configuration.
+     *
+     * @param app Information about the desired application.
+     * @param configuration Overridden configuration when loading the Resources
+     *
+     * @return Returns the application's Resources.
+     * @throws NameNotFoundException Thrown if the resources for the given
+     * application could not be loaded (most likely because it was uninstalled).
+     */
+    @NonNull
+    public Resources getResourcesForApplication(@NonNull ApplicationInfo app, @Nullable
+            Configuration configuration) throws NameNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
      * Retrieve the resources associated with an application.  Given the full
      * package name of an application, retrieves the information about it and
      * calls getResources() to return its application's resources.  If the
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index 02fb06b..bce4b87 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -256,6 +256,8 @@
         try {
             if (obj != null) {
                 Signature other = (Signature)obj;
+                // Note, some classes, such as PackageParser.SigningDetails, rely on equals
+                // only comparing the mSignature arrays without the flags.
                 return this == other || Arrays.equals(mSignature, other.mSignature);
             }
         } catch (ClassCastException e) {
@@ -268,6 +270,8 @@
         if (mHaveHashCode) {
             return mHashCode;
         }
+        // Note, similar to equals some classes rely on the hash code not including
+        // the flags for Set membership checks.
         mHashCode = Arrays.hashCode(mSignature);
         mHaveHashCode = true;
         return mHashCode;
diff --git a/core/java/android/hardware/Battery.java b/core/java/android/hardware/Battery.java
new file mode 100644
index 0000000..24c8d76
--- /dev/null
+++ b/core/java/android/hardware/Battery.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+import android.annotation.FloatRange;
+import android.annotation.IntDef;
+import android.os.BatteryManager;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * The Battery class is a representation of a single battery on a device.
+ */
+public abstract class Battery {
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "STATUS_" }, value = {
+            STATUS_UNKNOWN,
+            STATUS_CHARGING,
+            STATUS_DISCHARGING,
+            STATUS_NOT_CHARGING,
+            STATUS_FULL
+    })
+    public @interface BatteryStatus {
+    }
+
+    /** Battery status is unknown. */
+    public static final int STATUS_UNKNOWN = BatteryManager.BATTERY_STATUS_UNKNOWN;
+    /** Battery is charging. */
+    public static final int STATUS_CHARGING = BatteryManager.BATTERY_STATUS_CHARGING;
+    /** Battery is discharging. */
+    public static final int STATUS_DISCHARGING = BatteryManager.BATTERY_STATUS_DISCHARGING;
+    /** Battery is connected to power but not charging. */
+    public static final int STATUS_NOT_CHARGING = BatteryManager.BATTERY_STATUS_NOT_CHARGING;
+    /** Battery is full. */
+    public static final int STATUS_FULL = BatteryManager.BATTERY_STATUS_FULL;
+
+    /**
+     * Check whether the hardware has a battery.
+     *
+     * @return True if the hardware has a battery, else false.
+     */
+    public abstract boolean hasBattery();
+
+    /**
+     * Get the battery status.
+     *
+     * @return the battery status.
+     */
+    public abstract @BatteryStatus int getStatus();
+
+    /**
+     * Get remaining battery capacity as float percentage [0.0f, 1.0f] of total capacity
+     * Returns -1 when battery capacity can't be read.
+     *
+     * @return the battery capacity.
+     */
+    public abstract @FloatRange(from = -1.0f, to = 1.0f) float getCapacity();
+}
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index b39df4d..c69c47f 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -93,6 +93,10 @@
     int[] getVibratorIds(int deviceId);
     boolean isVibrating(int deviceId);
 
+    // Input device battery query.
+    int getBatteryStatus(int deviceId);
+    int getBatteryCapacity(int deviceId);
+
     void setPointerIconType(int typeId);
     void setCustomPointerIcon(in PointerIcon icon);
 
diff --git a/core/java/android/hardware/input/InputDeviceBattery.java b/core/java/android/hardware/input/InputDeviceBattery.java
new file mode 100644
index 0000000..0fe124e
--- /dev/null
+++ b/core/java/android/hardware/input/InputDeviceBattery.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.IInputConstants.INVALID_BATTERY_CAPACITY;
+
+import android.hardware.Battery;
+
+/**
+ * Battery implementation for input devices.
+ *
+ * @hide
+ */
+public final class InputDeviceBattery extends Battery {
+    private static final float NULL_BATTERY_CAPACITY = -1.0f;
+
+    private final InputManager mInputManager;
+    private final int mDeviceId;
+    private final boolean mHasBattery;
+
+    InputDeviceBattery(InputManager inputManager, int deviceId, boolean hasBattery) {
+        mInputManager = inputManager;
+        mDeviceId = deviceId;
+        mHasBattery = hasBattery;
+    }
+
+    @Override
+    public boolean hasBattery() {
+        return mHasBattery;
+    }
+
+    @Override
+    public int getStatus() {
+        if (!mHasBattery) {
+            return BATTERY_STATUS_UNKNOWN;
+        }
+        return mInputManager.getBatteryStatus(mDeviceId);
+    }
+
+    @Override
+    public float getCapacity() {
+        if (mHasBattery) {
+            int capacity = mInputManager.getBatteryCapacity(mDeviceId);
+            if (capacity != INVALID_BATTERY_CAPACITY) {
+                return (float) capacity / 100.0f;
+            }
+        }
+        return NULL_BATTERY_CAPACITY;
+    }
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index e63dc11..185c59d 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1245,6 +1245,32 @@
     }
 
     /**
+     * Get the battery status of the input device
+     * @param deviceId The input device ID
+     * @hide
+     */
+    public int getBatteryStatus(int deviceId) {
+        try {
+            return mIm.getBatteryStatus(deviceId);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get the remaining battery capacity of the input device
+     * @param deviceId The input device ID
+     * @hide
+     */
+    public int getBatteryCapacity(int deviceId) {
+        try {
+            return mIm.getBatteryCapacity(deviceId);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Add a runtime association between the input port and the display port. This overrides any
      * static associations.
      * @param inputPort The port of the input device.
@@ -1471,6 +1497,15 @@
     }
 
     /**
+     * Gets a battery object associated with an input device, assuming it has one.
+     * @return The battery, never null.
+     * @hide
+     */
+    public InputDeviceBattery getInputDeviceBattery(int deviceId, boolean hasBattery) {
+        return new InputDeviceBattery(this, deviceId, hasBattery);
+    }
+
+    /**
      * Listens for changes in input devices.
      */
     public interface InputDeviceListener {
diff --git a/core/java/android/hardware/location/ContextHubClientCallback.java b/core/java/android/hardware/location/ContextHubClientCallback.java
index 20fa753..b31b85f 100644
--- a/core/java/android/hardware/location/ContextHubClientCallback.java
+++ b/core/java/android/hardware/location/ContextHubClientCallback.java
@@ -15,6 +15,7 @@
  */
 package android.hardware.location;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 
 import java.util.concurrent.Executor;
@@ -101,4 +102,34 @@
      * @param nanoAppId the ID of the nanoapp that had been disabled
      */
     public void onNanoAppDisabled(ContextHubClient client, long nanoAppId) {}
+
+    /**
+     * Callback invoked when a {@link ContextHubClient}'s authorization to communicate with a
+     * nanoapp changes. This typically happens as a result of the app that created the
+     * {@link ContextHubClient} gaining or losing the permissions required to communicate with a
+     * nanoapp.
+     *
+     * An example of the connection callbacks looks like:
+     * 1) {@link ContextHubClient} sends message to nanoapp and holds required permissions
+     * 2) {@link ContextHubClient} loses required permissions
+     * 3) Callback invoked with the nanoapp ID and
+     *    {@link ContextHubManager#AUTHORIZATION_DENIED_GRACE_PERIOD}
+     * 4) {@link ContextHubClient} performs any cleanup required with the nanoapp
+     * 5) Callback invoked with the nanoapp ID and {@link ContextHubManager#AUTHORIZATION_DENIED}.
+     *    At this point, any further attempts of communication between the nanoapp and the
+     *    {@link ContextHubClient} will be dropped by the contexthub along with
+     *    {@link ContextHubManager#AUTHORIZATION_DENIED} being sent. The {@link ContextHubClient}
+     *    should assume no communciation can happen again until
+     *    {@link ContextHubManager#AUTHORIZATION_GRANTED} is received.
+     *
+     * @param client the client that is associated with this callback
+     * @param nanoAppId the ID of the nanoapp associated with the new
+     * authorization state
+     * @param authorization the authorization state denoting the ability of the
+     * client to communicate with the nanoapp
+     */
+    public void onClientAuthorizationChanged(
+            @NonNull ContextHubClient client,
+            long nanoAppId,
+            @ContextHubManager.AuthorizationState int authorization) {}
 }
diff --git a/core/java/android/hardware/location/ContextHubIntentEvent.java b/core/java/android/hardware/location/ContextHubIntentEvent.java
index 917f62b..3e8f421 100644
--- a/core/java/android/hardware/location/ContextHubIntentEvent.java
+++ b/core/java/android/hardware/location/ContextHubIntentEvent.java
@@ -43,39 +43,45 @@
 
     private final int mNanoAppAbortCode;
 
+    private final int mClientAuthorizationState;
+
     private ContextHubIntentEvent(
             @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType,
-            long nanoAppId, NanoAppMessage nanoAppMessage, int nanoAppAbortCode) {
+            long nanoAppId, NanoAppMessage nanoAppMessage, int nanoAppAbortCode,
+            @ContextHubManager.AuthorizationState int clientAuthorizationState) {
         mContextHubInfo = contextHubInfo;
         mEventType = eventType;
         mNanoAppId = nanoAppId;
         mNanoAppMessage = nanoAppMessage;
         mNanoAppAbortCode = nanoAppAbortCode;
+        mClientAuthorizationState = clientAuthorizationState;
     }
 
     private ContextHubIntentEvent(
             @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType) {
         this(contextHubInfo, eventType, -1 /* nanoAppId */, null /* nanoAppMessage */,
-                -1 /* nanoAppAbortCode */);
+                -1 /* nanoAppAbortCode */, 0 /* clientAuthorizationState */);
     }
 
     private ContextHubIntentEvent(
             @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType,
             long nanoAppId) {
         this(contextHubInfo, eventType, nanoAppId, null /* nanoAppMessage */,
-                -1 /* nanoAppAbortCode */);
+                -1 /* nanoAppAbortCode */, 0 /* clientAuthorizationState */);
     }
 
     private ContextHubIntentEvent(
             @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType,
             long nanoAppId, @NonNull NanoAppMessage nanoAppMessage) {
-        this(contextHubInfo, eventType, nanoAppId, nanoAppMessage, -1 /* nanoAppAbortCode */);
+        this(contextHubInfo, eventType, nanoAppId, nanoAppMessage, -1 /* nanoAppAbortCode */,
+                0 /* clientAuthorizationState */);
     }
 
     private ContextHubIntentEvent(
             @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType,
             long nanoAppId, int nanoAppAbortCode) {
-        this(contextHubInfo, eventType, nanoAppId, null /* nanoAppMessage */, nanoAppAbortCode);
+        this(contextHubInfo, eventType, nanoAppId, null /* nanoAppMessage */, nanoAppAbortCode,
+                0 /* clientAuthorizationState */);
     }
 
     /**
@@ -105,7 +111,8 @@
             case ContextHubManager.EVENT_NANOAPP_ENABLED:
             case ContextHubManager.EVENT_NANOAPP_DISABLED:
             case ContextHubManager.EVENT_NANOAPP_ABORTED:
-            case ContextHubManager.EVENT_NANOAPP_MESSAGE: // fall through
+            case ContextHubManager.EVENT_NANOAPP_MESSAGE:
+            case ContextHubManager.EVENT_CLIENT_AUTHORIZATION: // fall through
                 long nanoAppId = getLongExtraOrThrow(intent, ContextHubManager.EXTRA_NANOAPP_ID);
                 if (eventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) {
                     hasExtraOrThrow(intent, ContextHubManager.EXTRA_MESSAGE);
@@ -120,6 +127,11 @@
                     int nanoAppAbortCode = getIntExtraOrThrow(
                             intent, ContextHubManager.EXTRA_NANOAPP_ABORT_CODE);
                     event = new ContextHubIntentEvent(info, eventType, nanoAppId, nanoAppAbortCode);
+                } else if (eventType == ContextHubManager.EVENT_CLIENT_AUTHORIZATION) {
+                    int authState = getIntExtraOrThrow(
+                            intent, ContextHubManager.EXTRA_CLIENT_AUTHORIZATION_STATE);
+                    event = new ContextHubIntentEvent(info, eventType, nanoAppId,
+                            null /* nanoAppMessage */, -1 /* nanoAppAbortCode */, authState);
                 } else {
                     event = new ContextHubIntentEvent(info, eventType, nanoAppId);
                 }
@@ -192,6 +204,21 @@
         return mNanoAppMessage;
     }
 
+    /**
+     * @return the client authorization state
+     *
+     * @throws UnsupportedOperationException if this was not a client authorization state event
+     */
+    @ContextHubManager.AuthorizationState
+    public int getClientAuthorizationState() {
+        if (mEventType != ContextHubManager.EVENT_CLIENT_AUTHORIZATION) {
+            throw new UnsupportedOperationException(
+                    "Cannot invoke getClientAuthorizationState() on non-authorization event: "
+                    + mEventType);
+        }
+        return mClientAuthorizationState;
+    }
+
     @NonNull
     @Override
     public String toString() {
@@ -207,6 +234,9 @@
         if (mEventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) {
             out += ", nanoAppMessage = " + mNanoAppMessage;
         }
+        if (mEventType == ContextHubManager.EVENT_CLIENT_AUTHORIZATION) {
+            out += ", clientAuthState = " + mClientAuthorizationState;
+        }
 
         return out + "]";
     }
@@ -233,6 +263,9 @@
                     if (mEventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) {
                         isEqual &= other.getNanoAppMessage().equals(mNanoAppMessage);
                     }
+                    if (mEventType == ContextHubManager.EVENT_CLIENT_AUTHORIZATION) {
+                        isEqual &= other.getClientAuthorizationState() == mClientAuthorizationState;
+                    }
                 } catch (UnsupportedOperationException e) {
                     isEqual = false;
                 }
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index d444807..ebb3021 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -59,6 +59,12 @@
     private static final String TAG = "ContextHubManager";
 
     /**
+     * An extra of type int describing the client's authorization state.
+     */
+    public static final String EXTRA_CLIENT_AUTHORIZATION_STATE =
+            "android.hardware.location.extra.CLIENT_AUTHORIZATION_STATE";
+
+    /**
      * An extra of type {@link ContextHubInfo} describing the source of the event.
      */
     public static final String EXTRA_CONTEXT_HUB_INFO =
@@ -86,6 +92,42 @@
     public static final String EXTRA_MESSAGE = "android.hardware.location.extra.MESSAGE";
 
     /**
+     * Constants describing if a {@link ContextHubClient} and a {@link NanoApp} are authorized to
+     * communicate.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "AUTHORIZATION_" }, value = {
+        AUTHORIZATION_DENIED,
+        AUTHORIZATION_DENIED_GRACE_PERIOD,
+        AUTHORIZATION_GRANTED,
+    })
+    public @interface AuthorizationState { }
+
+    /**
+     * Indicates that the {@link ContextHubClient} can no longer communicate with a nanoapp. If the
+     * {@link ContextHubClient} attempts to send messages to the nanoapp, it will continue to
+     * receive this authorization state if the connection is still closed.
+     */
+    public static final int AUTHORIZATION_DENIED = 0;
+
+    /**
+     * Indicates the {@link ContextHubClient} will soon lose its authorization to communicate with a
+     * nanoapp. The {@link ContextHubClient} must perform any cleanup with the nanoapp as soon as
+     * possible.
+     *
+     * Note that the time between this state event and {@link AUTHORIZATION_DENIED} must be enough
+     * for the {@link ContextHubClient} to send at least one message to the nanoapp.
+     */
+    public static final int AUTHORIZATION_DENIED_GRACE_PERIOD = 1;
+
+    /**
+     * The {@link ContextHubClient} is authorized to communicate with the nanoapp.
+     */
+    public static final int AUTHORIZATION_GRANTED = 2;
+
+    /**
      * Constants describing the type of events from a Context Hub.
      * {@hide}
      */
@@ -98,6 +140,7 @@
         EVENT_NANOAPP_ABORTED,
         EVENT_NANOAPP_MESSAGE,
         EVENT_HUB_RESET,
+        EVENT_CLIENT_AUTHORIZATION,
     })
     public @interface Event { }
 
@@ -138,6 +181,14 @@
      */
     public static final int EVENT_HUB_RESET = 6;
 
+    /**
+     * An event describing a client authorization state change. See
+     * {@link ContextHubClientCallback#onClientAuthorizationChanged} for more details on when this
+     * event will be sent. Contains the EXTRA_NANOAPP_ID and EXTRA_CLIENT_AUTHORIZATION_STATE
+     * extras.
+     */
+    public static final int EVENT_CLIENT_AUTHORIZATION = 7;
+
     private final Looper mMainLooper;
     private final IContextHubService mService;
     private Callback mCallback;
@@ -747,6 +798,14 @@
             public void onNanoAppDisabled(long nanoAppId) {
                 executor.execute(() -> callback.onNanoAppDisabled(client, nanoAppId));
             }
+
+            @Override
+            public void onClientAuthorizationChanged(
+                    long nanoAppId, @ContextHubManager.AuthorizationState int authorization) {
+                executor.execute(
+                        () -> callback.onClientAuthorizationChanged(
+                                client, nanoAppId, authorization));
+            }
         };
     }
 
@@ -757,9 +816,10 @@
      * registration succeeds, the client can send messages to nanoapps through the returned
      * {@link ContextHubClient} object, and receive notifications through the provided callback.
      *
+     * @param context  the context of the application
      * @param hubInfo  the hub to attach this client to
-     * @param callback the notification callback to register
      * @param executor the executor to invoke the callback
+     * @param callback the notification callback to register
      * @return the registered client object
      *
      * @throws IllegalArgumentException if hubInfo does not represent a valid hub
@@ -773,8 +833,9 @@
             android.Manifest.permission.ACCESS_CONTEXT_HUB
     })
     @NonNull public ContextHubClient createClient(
-            @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback,
-            @NonNull @CallbackExecutor Executor executor) {
+            @Nullable Context context, @NonNull ContextHubInfo hubInfo,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull ContextHubClientCallback callback) {
         Objects.requireNonNull(callback, "Callback cannot be null");
         Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null");
         Objects.requireNonNull(executor, "Executor cannot be null");
@@ -783,9 +844,14 @@
         IContextHubClientCallback clientInterface = createClientCallback(
                 client, callback, executor);
 
+        String attributionTag = null;
+        if (context != null) {
+            attributionTag = context.getAttributionTag();
+        }
+
         IContextHubClient clientProxy;
         try {
-            clientProxy = mService.createClient(hubInfo.getId(), clientInterface);
+            clientProxy = mService.createClient(hubInfo.getId(), clientInterface, attributionTag);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -794,19 +860,25 @@
         return client;
     }
 
+
+    /**
+     * Equivalent to
+     * {@link #createClient(ContextHubInfo, Executor, String, ContextHubClientCallback)}
+     * with the {@link Context} being set to null.
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
+    @NonNull public ContextHubClient createClient(
+            @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback,
+            @NonNull @CallbackExecutor Executor executor) {
+        return createClient(null /* context */, hubInfo, executor, callback);
+    }
+
     /**
      * Equivalent to {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)}
      * with the executor using the main thread's Looper.
-     *
-     * @param hubInfo  the hub to attach this client to
-     * @param callback the notification callback to register
-     * @return the registered client object
-     *
-     * @throws IllegalArgumentException if hubInfo does not represent a valid hub
-     * @throws IllegalStateException    if there were too many registered clients at the service
-     * @throws NullPointerException     if callback or hubInfo is null
-     *
-     * @see ContextHubClientCallback
      */
     @RequiresPermission(anyOf = {
             android.Manifest.permission.LOCATION_HARDWARE,
@@ -814,7 +886,8 @@
     })
     @NonNull public ContextHubClient createClient(
             @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback) {
-        return createClient(hubInfo, callback, new HandlerExecutor(Handler.getMain()));
+        return createClient(null /* context */, hubInfo, new HandlerExecutor(Handler.getMain()),
+                            callback);
     }
 
     /**
@@ -848,6 +921,8 @@
      * on the provided PendingIntent, then the client will be automatically unregistered by the
      * service.
      *
+     * @param context       the context of the application. If a PendingIntent client is recreated,
+     * the latest state in the context will be used and old state will be discarded
      * @param hubInfo       the hub to attach this client to
      * @param pendingIntent the PendingIntent to register to the client
      * @param nanoAppId     the ID of the nanoapp that Intent events will be generated for
@@ -862,16 +937,22 @@
             android.Manifest.permission.ACCESS_CONTEXT_HUB
     })
     @NonNull public ContextHubClient createClient(
-            @NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) {
+            @Nullable Context context, @NonNull ContextHubInfo hubInfo,
+            @NonNull PendingIntent pendingIntent, long nanoAppId) {
         Objects.requireNonNull(pendingIntent);
         Objects.requireNonNull(hubInfo);
 
         ContextHubClient client = new ContextHubClient(hubInfo, true /* persistent */);
 
+        String attributionTag = null;
+        if (context != null) {
+            attributionTag = context.getAttributionTag();
+        }
+
         IContextHubClient clientProxy;
         try {
             clientProxy = mService.createPendingIntentClient(
-                    hubInfo.getId(), pendingIntent, nanoAppId);
+                    hubInfo.getId(), pendingIntent, nanoAppId, attributionTag);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -881,6 +962,19 @@
     }
 
     /**
+     * Equivalent to {@link #createClient(ContextHubInfo, PendingIntent, long, String)}
+     * with {@link Context} being set to null.
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.LOCATION_HARDWARE,
+            android.Manifest.permission.ACCESS_CONTEXT_HUB
+    })
+    @NonNull public ContextHubClient createClient(
+            @NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) {
+        return createClient(null /* context */, hubInfo, pendingIntent, nanoAppId);
+    }
+
+    /**
      * Unregister a callback for receive messages from the context hub.
      *
      * @see Callback
diff --git a/core/java/android/hardware/location/IContextHubClientCallback.aidl b/core/java/android/hardware/location/IContextHubClientCallback.aidl
index 1c76bcb..bcd6b08 100644
--- a/core/java/android/hardware/location/IContextHubClientCallback.aidl
+++ b/core/java/android/hardware/location/IContextHubClientCallback.aidl
@@ -46,4 +46,7 @@
 
     // Callback invoked when a nanoapp is disabled at the attached Context Hub.
     void onNanoAppDisabled(long nanoAppId);
+
+    // Callback invoked when the authorization state of a client changes.
+    void onClientAuthorizationChanged(long nanoAppId, int authorization);
 }
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
index 04cc563..4961195 100644
--- a/core/java/android/hardware/location/IContextHubService.aidl
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -59,11 +59,13 @@
     int sendMessage(int contextHubHandle, int nanoAppHandle, in ContextHubMessage msg);
 
     // Creates a client to send and receive messages
-    IContextHubClient createClient(int contextHubId, in IContextHubClientCallback client);
+    IContextHubClient createClient(
+            int contextHubId, in IContextHubClientCallback client, in String attributionTag);
 
     // Creates a PendingIntent-based client to send and receive messages
     IContextHubClient createPendingIntentClient(
-            int contextHubId, in PendingIntent pendingIntent, long nanoAppId);
+            int contextHubId, in PendingIntent pendingIntent, long nanoAppId,
+            in String attributionTag);
 
     // Returns a list of ContextHub objects of available hubs
     List<ContextHubInfo> getContextHubs();
diff --git a/core/java/android/hardware/location/NanoAppState.java b/core/java/android/hardware/location/NanoAppState.java
index 8de7ecd..96b1f19 100644
--- a/core/java/android/hardware/location/NanoAppState.java
+++ b/core/java/android/hardware/location/NanoAppState.java
@@ -15,10 +15,14 @@
  */
 package android.hardware.location;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * A class describing the nanoapp state information resulting from a query to a Context Hub.
  *
@@ -29,11 +33,21 @@
     private long mNanoAppId;
     private int mNanoAppVersion;
     private boolean mIsEnabled;
+    private List<String> mNanoAppPermissions;
 
     public NanoAppState(long nanoAppId, int appVersion, boolean enabled) {
         mNanoAppId = nanoAppId;
         mNanoAppVersion = appVersion;
         mIsEnabled = enabled;
+        mNanoAppPermissions = new ArrayList<String>();
+    }
+
+    public NanoAppState(long nanoAppId, int appVersion, boolean enabled,
+                        @NonNull List<String> nanoAppPermissions) {
+        mNanoAppId = nanoAppId;
+        mNanoAppVersion = appVersion;
+        mIsEnabled = enabled;
+        mNanoAppPermissions = nanoAppPermissions;
     }
 
     /**
@@ -57,10 +71,19 @@
         return mIsEnabled;
     }
 
+    /**
+     * @return List of Android permissions that are required to communicate with this app.
+     */
+    public @NonNull List<String> getNanoAppPermissions() {
+        return mNanoAppPermissions;
+    }
+
     private NanoAppState(Parcel in) {
         mNanoAppId = in.readLong();
         mNanoAppVersion = in.readInt();
         mIsEnabled = (in.readInt() == 1);
+        mNanoAppPermissions = new ArrayList<String>();
+        in.readStringList(mNanoAppPermissions);
     }
 
     @Override
@@ -73,6 +96,7 @@
         out.writeLong(mNanoAppId);
         out.writeInt(mNanoAppVersion);
         out.writeInt(mIsEnabled ? 1 : 0);
+        out.writeStringList(mNanoAppPermissions);
     }
 
     public static final @android.annotation.NonNull Creator<NanoAppState> CREATOR =
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6dab4c0..f6ef8a3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -13393,6 +13393,24 @@
                 "euicc_factory_reset_timeout_millis";
 
         /**
+         * Flag to set the waiting time for euicc slot switch.
+         * Type: long
+         *
+         * @hide
+         */
+        public static final String EUICC_SWITCH_SLOT_TIMEOUT_MILLIS =
+                "euicc_switch_slot_timeout_millis";
+
+        /**
+         * Flag to set the waiting time for enabling multi SIM slot.
+         * Type: long
+         *
+         * @hide
+         */
+        public static final String ENABLE_MULTI_SLOT_TIMEOUT_MILLIS =
+                "enable_multi_slot_timeout_millis";
+
+        /**
          * Flag to set the timeout for when to refresh the storage settings cached data.
          * Type: long
          *
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index e0f3018..44daeff 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -46,7 +46,7 @@
     void onNotificationChannelGroupModification(String pkgName, in UserHandle user, in NotificationChannelGroup group, int modificationType);
 
     // assistants only
-    void onNotificationEnqueuedWithChannel(in IStatusBarNotificationHolder notificationHolder, in NotificationChannel channel);
+    void onNotificationEnqueuedWithChannel(in IStatusBarNotificationHolder notificationHolder, in NotificationChannel channel, in NotificationRankingUpdate update);
     void onNotificationSnoozedUntilContext(in IStatusBarNotificationHolder notificationHolder, String snoozeCriterionId);
     void onNotificationsSeen(in List<String> keys);
     void onPanelRevealed(int items);
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index cf2152c..1d49a72 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -126,7 +126,7 @@
      * {@link #onNotificationEnqueued(StatusBarNotification, NotificationChannel)}.</p>
      *
      * @param sbn the new notification
-     * @return an adjustment or null to take no action, within 100ms.
+     * @return an adjustment or null to take no action, within 200ms.
      */
     abstract public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn);
 
@@ -135,7 +135,7 @@
      *
      * @param sbn the new notification
      * @param channel the channel the notification was posted to
-     * @return an adjustment or null to take no action, within 100ms.
+     * @return an adjustment or null to take no action, within 200ms.
      */
     public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn,
             @NonNull NotificationChannel channel) {
@@ -143,6 +143,20 @@
     }
 
     /**
+     * A notification was posted by an app. Called before post.
+     *
+     * @param sbn the new notification
+     * @param channel the channel the notification was posted to
+     * @param rankingMap The current ranking map that can be used to retrieve ranking information
+     *                   for active notifications.
+     * @return an adjustment or null to take no action, within 200ms.
+     */
+    public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn,
+            @NonNull NotificationChannel channel, @NonNull RankingMap rankingMap) {
+        return onNotificationEnqueued(sbn, channel);
+    }
+
+    /**
      * Implement this method to learn when notifications are removed, how they were interacted with
      * before removal, and why they were removed.
      * <p>
@@ -316,7 +330,7 @@
     private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper {
         @Override
         public void onNotificationEnqueuedWithChannel(IStatusBarNotificationHolder sbnHolder,
-                NotificationChannel channel) {
+                NotificationChannel channel, NotificationRankingUpdate update) {
             StatusBarNotification sbn;
             try {
                 sbn = sbnHolder.get();
@@ -330,9 +344,11 @@
                 return;
             }
 
+            applyUpdateLocked(update);
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = sbn;
             args.arg2 = channel;
+            args.arg3 = getCurrentRanking();
             mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED,
                     args).sendToTarget();
         }
@@ -472,8 +488,9 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     StatusBarNotification sbn = (StatusBarNotification) args.arg1;
                     NotificationChannel channel = (NotificationChannel) args.arg2;
+                    RankingMap ranking = (RankingMap) args.arg3;
                     args.recycle();
-                    Adjustment adjustment = onNotificationEnqueued(sbn, channel);
+                    Adjustment adjustment = onNotificationEnqueued(sbn, channel, ranking);
                     setAdjustmentIssuer(adjustment);
                     if (adjustment != null) {
                         if (!isBound()) {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index c41e599..64cddc3 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1431,7 +1431,8 @@
 
         @Override
         public void onNotificationEnqueuedWithChannel(
-                IStatusBarNotificationHolder notificationHolder, NotificationChannel channel)
+                IStatusBarNotificationHolder notificationHolder, NotificationChannel channel,
+                NotificationRankingUpdate update)
                 throws RemoteException {
             // no-op in the listener
         }
diff --git a/core/java/android/util/imetracing/ImeTracing.java b/core/java/android/util/imetracing/ImeTracing.java
index 723f1dd..49ff237 100644
--- a/core/java/android/util/imetracing/ImeTracing.java
+++ b/core/java/android/util/imetracing/ImeTracing.java
@@ -28,6 +28,8 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.inputmethod.InputMethodManager;
 
+import com.android.internal.inputmethod.Completable;
+import com.android.internal.inputmethod.ResultCallbacks;
 import com.android.internal.view.IInputMethodManager;
 
 import java.io.PrintWriter;
@@ -91,7 +93,9 @@
      * @param where
      */
     public void sendToService(byte[] protoDump, int source, String where) throws RemoteException {
-        mService.startProtoDump(protoDump, source, where);
+        final Completable.Void value = Completable.createVoid();
+        mService.startProtoDump(protoDump, source, where, ResultCallbacks.of(value));
+        Completable.getResult(value);
     }
 
     /**
diff --git a/core/java/android/util/imetracing/OWNERS b/core/java/android/util/imetracing/OWNERS
new file mode 100644
index 0000000..885fd0a
--- /dev/null
+++ b/core/java/android/util/imetracing/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index f4b90e1..bc03222 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -22,6 +22,7 @@
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.hardware.Battery;
 import android.hardware.SensorManager;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
@@ -73,6 +74,7 @@
     private final boolean mHasMicrophone;
     private final boolean mHasButtonUnderPad;
     private final boolean mHasSensor;
+    private final boolean mHasBattery;
     private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
 
     @GuardedBy("mMotionRanges")
@@ -84,6 +86,9 @@
     @GuardedBy("mMotionRanges")
     private SensorManager mSensorManager;
 
+    @GuardedBy("mMotionRanges")
+    private Battery mBattery;
+
     /**
      * A mask for input source classes.
      *
@@ -323,6 +328,13 @@
     public static final int SOURCE_HDMI = 0x02000000 | SOURCE_CLASS_BUTTON;
 
     /**
+     * The input source is a sensor associated with the input device.
+     *
+     * @see #SOURCE_CLASS_NONE
+     */
+    public static final int SOURCE_SENSOR = 0x04000000 | SOURCE_CLASS_NONE;
+
+    /**
      * A special input source constant that is used when filtering input devices
      * to match devices that provide any type of input source.
      */
@@ -448,7 +460,7 @@
     public InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
             int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
             KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
-            boolean hasButtonUnderPad, boolean hasSensor) {
+            boolean hasButtonUnderPad, boolean hasSensor, boolean hasBattery) {
         mId = id;
         mGeneration = generation;
         mControllerNumber = controllerNumber;
@@ -464,6 +476,7 @@
         mHasMicrophone = hasMicrophone;
         mHasButtonUnderPad = hasButtonUnderPad;
         mHasSensor = hasSensor;
+        mHasBattery = hasBattery;
         mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
     }
 
@@ -483,6 +496,7 @@
         mHasMicrophone = in.readInt() != 0;
         mHasButtonUnderPad = in.readInt() != 0;
         mHasSensor = in.readInt() != 0;
+        mHasBattery = in.readInt() != 0;
         mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
 
         int numRanges = in.readInt();
@@ -830,6 +844,22 @@
     }
 
     /**
+     * Gets the battery object associated with the device, if there is one.
+     * Even if the device does not have a battery, the result is never null.
+     * Use {@link Battery#hasBattery} to determine whether a battery is
+     * present.
+     *
+     * @return The battery object associated with the device, never null.
+     */
+    @NonNull
+    public Battery getBattery() {
+        if (mBattery == null) {
+            mBattery = InputManager.getInstance().getInputDeviceBattery(mId, mHasBattery);
+        }
+        return mBattery;
+    }
+
+    /**
      * Gets the sensor manager service associated with the input device.
      * Even if the device does not have a sensor, the result is never null.
      * Use {@link SensorManager#getSensorList} to get a full list of all supported sensors.
@@ -1051,6 +1081,7 @@
         out.writeInt(mHasMicrophone ? 1 : 0);
         out.writeInt(mHasButtonUnderPad ? 1 : 0);
         out.writeInt(mHasSensor ? 1 : 0);
+        out.writeInt(mHasBattery ? 1 : 0);
 
         final int numRanges = mMotionRanges.size();
         out.writeInt(numRanges);
@@ -1097,6 +1128,8 @@
 
         description.append("  Has Sensor: ").append(mHasSensor).append("\n");
 
+        description.append("  Has battery: ").append(mHasBattery).append("\n");
+
         description.append("  Has mic: ").append(mHasMicrophone).append("\n");
 
         description.append("  Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index bf377b0..d68e903 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -106,7 +106,9 @@
     public static final int ITYPE_NAVIGATION_BAR = 1;
     public static final int ITYPE_CAPTION_BAR = 2;
 
-    public static final int ITYPE_TOP_GESTURES = 3;
+    // The always visible types are visible to all windows regardless of the z-order.
+    public static final int FIRST_ALWAYS_VISIBLE_TYPE = 3;
+    public static final int ITYPE_TOP_GESTURES = FIRST_ALWAYS_VISIBLE_TYPE;
     public static final int ITYPE_BOTTOM_GESTURES = 4;
     public static final int ITYPE_LEFT_GESTURES = 5;
     public static final int ITYPE_RIGHT_GESTURES = 6;
@@ -117,15 +119,16 @@
     public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9;
     public static final int ITYPE_RIGHT_MANDATORY_GESTURES = 10;
 
-    public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 11;
-    public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 12;
-    public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 13;
-    public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 14;
+    public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 11;
+    public static final int ITYPE_TOP_DISPLAY_CUTOUT = 12;
+    public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 13;
+    public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 14;
+    public static final int LAST_ALWAYS_VISIBLE_TYPE = ITYPE_BOTTOM_DISPLAY_CUTOUT;
 
-    public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 15;
-    public static final int ITYPE_TOP_DISPLAY_CUTOUT = 16;
-    public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 17;
-    public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 18;
+    public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 15;
+    public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 16;
+    public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 17;
+    public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 18;
 
     /** Input method window. */
     public static final int ITYPE_IME = 19;
@@ -182,6 +185,18 @@
     }
 
     /**
+     * Mirror the always visible sources from the other state. They will share the same object for
+     * the always visible types.
+     *
+     * @param other the state to mirror the mirrored sources from.
+     */
+    public void mirrorAlwaysVisibleInsetsSources(InsetsState other) {
+        for (int type = FIRST_ALWAYS_VISIBLE_TYPE; type <= LAST_ALWAYS_VISIBLE_TYPE; type++) {
+            mSources[type] = other.mSources[type];
+        }
+    }
+
+    /**
      * Calculates {@link WindowInsets} based on the current source configuration.
      *
      * @param frame The frame to calculate the insets relative to.
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 0a1a231..acd2507 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -750,18 +750,22 @@
     private abstract static class CaptureArgs {
         private final int mPixelFormat;
         private final Rect mSourceCrop = new Rect();
-        private final float mFrameScale;
+        private final float mFrameScaleX;
+        private final float mFrameScaleY;
         private final boolean mCaptureSecureLayers;
         private final boolean mAllowProtected;
         private final long mUid;
+        private final boolean mGrayscale;
 
         private CaptureArgs(Builder<? extends Builder<?>> builder) {
             mPixelFormat = builder.mPixelFormat;
             mSourceCrop.set(builder.mSourceCrop);
-            mFrameScale = builder.mFrameScale;
+            mFrameScaleX = builder.mFrameScaleX;
+            mFrameScaleY = builder.mFrameScaleY;
             mCaptureSecureLayers = builder.mCaptureSecureLayers;
             mAllowProtected = builder.mAllowProtected;
             mUid = builder.mUid;
+            mGrayscale = builder.mGrayscale;
         }
 
         /**
@@ -772,10 +776,12 @@
         abstract static class Builder<T extends Builder<T>> {
             private int mPixelFormat = PixelFormat.RGBA_8888;
             private final Rect mSourceCrop = new Rect();
-            private float mFrameScale = 1;
+            private float mFrameScaleX = 1;
+            private float mFrameScaleY = 1;
             private boolean mCaptureSecureLayers;
             private boolean mAllowProtected;
             private long mUid = -1;
+            private boolean mGrayscale;
 
             /**
              * The desired pixel format of the returned buffer.
@@ -798,7 +804,18 @@
              * The desired scale of the returned buffer. The raw screen will be scaled up/down.
              */
             public T setFrameScale(float frameScale) {
-                mFrameScale = frameScale;
+                mFrameScaleX = frameScale;
+                mFrameScaleY = frameScale;
+                return getThis();
+            }
+
+            /**
+             * The desired scale of the returned buffer, allowing separate values for x and y scale.
+             * The raw screen will be scaled up/down.
+             */
+            public T setFrameScale(float frameScaleX, float frameScaleY) {
+                mFrameScaleX = frameScaleX;
+                mFrameScaleY = frameScaleY;
                 return getThis();
             }
 
@@ -834,6 +851,14 @@
             }
 
             /**
+             * Set whether the screenshot should use grayscale or not.
+             */
+            public T setGrayscale(boolean grayscale) {
+                mGrayscale = grayscale;
+                return getThis();
+            }
+
+            /**
              * Each sub class should return itself to allow the builder to chain properly
              */
             abstract T getThis();
@@ -929,7 +954,7 @@
     /**
      * The arguments class used to make layer capture requests.
      *
-     * @see #nativeCaptureLayers(LayerCaptureArgs)
+     * @see #nativeCaptureLayers(LayerCaptureArgs, ScreenCaptureListener)
      * @hide
      */
     public static class LayerCaptureArgs extends CaptureArgs {
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index a76d46d1..f3111bd 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -858,7 +858,7 @@
     boolean reportFullscreenMode(boolean enabled);
 
     /**
-     * Have the editor perform spell checking around the current selection.
+     * Have the editor perform spell checking for the full content.
      *
      * <p>The editor can ignore this method call if it does not support spell checking.
      *
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 97d98fd..794b642 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -220,29 +220,26 @@
     }
 
     void onPerformSpellCheck() {
-        final int selectionStart = mTextView.getSelectionStart();
-        final int selectionEnd = mTextView.getSelectionEnd();
-        final int selectionRangeStart;
-        final int selectionRangeEnd;
-        if (selectionStart < selectionEnd) {
-            selectionRangeStart = selectionStart;
-            selectionRangeEnd = selectionEnd;
-        } else {
-            selectionRangeStart = selectionEnd;
-            selectionRangeEnd = selectionStart;
-        }
-        // Expand the range so that it (hopefully) includes the current sentence.
-        final int start = Math.max(0, selectionRangeStart - MIN_SENTENCE_LENGTH);
-        final int end = Math.min(mTextView.length(), selectionRangeEnd + MIN_SENTENCE_LENGTH);
+        // Triggers full content spell check.
+        final int start = 0;
+        final int end = mTextView.length();
         if (DBG) {
             Log.d(TAG, "performSpellCheckAroundSelection: " + start + ", " + end);
         }
-        spellCheck(start, end);
+        spellCheck(start, end, /* forceCheckWhenEditingWord= */ true);
     }
 
     public void spellCheck(int start, int end) {
+        spellCheck(start, end, /* forceCheckWhenEditingWord= */ false);
+    }
+
+    /**
+     * Requests to do spell check for text in the range (start, end).
+     */
+    public void spellCheck(int start, int end, boolean forceCheckWhenEditingWord) {
         if (DBG) {
-            Log.d(TAG, "Start spell-checking: " + start + ", " + end);
+            Log.d(TAG, "Start spell-checking: " + start + ", " + end + ", "
+                    + forceCheckWhenEditingWord);
         }
         final Locale locale = mTextView.getSpellCheckerLocale();
         final boolean isSessionActive = isSessionActive();
@@ -267,7 +264,7 @@
         for (int i = 0; i < length; i++) {
             final SpellParser spellParser = mSpellParsers[i];
             if (spellParser.isFinished()) {
-                spellParser.parse(start, end);
+                spellParser.parse(start, end, forceCheckWhenEditingWord);
                 return;
             }
         }
@@ -282,10 +279,14 @@
 
         SpellParser spellParser = new SpellParser();
         mSpellParsers[length] = spellParser;
-        spellParser.parse(start, end);
+        spellParser.parse(start, end, forceCheckWhenEditingWord);
     }
 
     private void spellCheck() {
+        spellCheck(/* forceCheckWhenEditingWord= */ false);
+    }
+
+    private void spellCheck(boolean forceCheckWhenEditingWord) {
         if (mSpellCheckerSession == null) return;
 
         Editable editable = (Editable) mTextView.getText();
@@ -295,6 +296,12 @@
         TextInfo[] textInfos = new TextInfo[mLength];
         int textInfosCount = 0;
 
+        if (DBG) {
+            Log.d(TAG, "forceCheckWhenEditingWord=" + forceCheckWhenEditingWord
+                    + ", mLength=" + mLength + ", cookie = " + mCookie
+                    + ", sel start = " + selectionStart + ", sel end = " + selectionEnd);
+        }
+
         for (int i = 0; i < mLength; i++) {
             final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
             if (mIds[i] < 0 || spellCheckSpan.isSpellCheckInProgress()) continue;
@@ -319,7 +326,7 @@
             } else {
                 isEditing = selectionEnd < start || selectionStart > end;
             }
-            if (start >= 0 && end > start && isEditing) {
+            if (start >= 0 && end > start && (forceCheckWhenEditingWord || isEditing)) {
                 spellCheckSpan.setSpellCheckInProgress(true);
                 final TextInfo textInfo = new TextInfo(editable, start, end, mCookie, mIds[i]);
                 textInfos[textInfosCount++] = textInfo;
@@ -546,7 +553,11 @@
     private class SpellParser {
         private Object mRange = new Object();
 
-        public void parse(int start, int end) {
+        // Forces to do spell checker even user is editing the word.
+        private boolean mForceCheckWhenEditingWord;
+
+        public void parse(int start, int end, boolean forceCheckWhenEditingWord) {
+            mForceCheckWhenEditingWord = forceCheckWhenEditingWord;
             final int max = mTextView.length();
             final int parseEnd;
             if (end > max) {
@@ -567,6 +578,7 @@
 
         public void stop() {
             removeRangeSpan((Editable) mTextView.getText());
+            mForceCheckWhenEditingWord = false;
         }
 
         private void setRangeSpan(Editable editable, int start, int end) {
@@ -617,7 +629,7 @@
                 if (DBG) {
                     Log.i(TAG, "No more spell check.");
                 }
-                removeRangeSpan(editable);
+                stop();
                 return;
             }
 
@@ -649,7 +661,7 @@
                     if (DBG) {
                         Log.i(TAG, "Incorrect range span.");
                     }
-                    removeRangeSpan(editable);
+                    stop();
                     return;
                 }
                 do {
@@ -778,7 +790,7 @@
                 removeRangeSpan(editable);
             }
 
-            spellCheck();
+            spellCheck(mForceCheckWhenEditingWord);
         }
 
         private <T> void removeSpansAt(Editable editable, int offset, T[] spans) {
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index 99692d0..7ade05c 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -5,3 +5,4 @@
 per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS
 per-file IVoice* = file:/core/java/android/service/voice/OWNERS
 per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
+per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 13358daf..1f09489 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -62,6 +62,11 @@
      */
     public static final String ENABLE_NAS_FEEDBACK = "enable_nas_feedback";
 
+    /**
+     * Whether the Notification Assistant can label a notification not a conversation
+     */
+    public static final String ENABLE_NAS_NOT_CONVERSATION = "enable_nas_not_conversation";
+
     // Flags related to screenshot intelligence
 
     /**
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index b8c066d..ea2fb88 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.hardware.SensorManager;
-import android.net.ConnectivityManager;
 import android.os.BatteryStats;
 import android.os.BatteryUsageStats;
 import android.os.BatteryUsageStatsQuery;
@@ -57,7 +56,7 @@
                 mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile));
                 mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile));
-                if (!isWifiOnlyDevice(mContext)) {
+                if (!BatteryStatsHelper.checkWifiOnly(mContext)) {
                     mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile));
                 }
                 mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
@@ -81,14 +80,6 @@
         return mPowerCalculators;
     }
 
-    private static boolean isWifiOnlyDevice(Context context) {
-        ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
-        if (cm == null) {
-            return false;
-        }
-        return !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
-    }
-
     /**
      * Returns a snapshot of battery attribution data.
      */
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 892c5a5..50bbfc5 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -91,11 +91,12 @@
     /** Remove the IME surface. Requires passing the currently focused window. */
     oneway void removeImeSurfaceFromWindow(in IBinder windowToken,
             in IVoidResultCallback resultCallback);
-    void startProtoDump(in byte[] protoDump, int source, String where);
+    oneway void startProtoDump(in byte[] protoDump, int source, String where,
+            in IVoidResultCallback resultCallback);
     oneway void isImeTraceEnabled(in IBooleanResultCallback resultCallback);
 
     // Starts an ime trace.
-    void startImeTrace();
+    oneway void startImeTrace(in IVoidResultCallback resultCallback);
     // Stops an ime trace.
-    void stopImeTrace();
+    oneway void stopImeTrace(in IVoidResultCallback resultCallback);
 }
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 4eaa016..9cc7243 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -70,7 +70,8 @@
                                           deviceInfo.isExternal(), deviceInfo.getSources(),
                                           deviceInfo.getKeyboardType(), kcmObj.get(),
                                           deviceInfo.hasVibrator(), hasMic,
-                                          deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor()));
+                                          deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor(),
+                                          deviceInfo.hasBattery()));
 
     const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
     for (const InputDeviceInfo::MotionRange& range: ranges) {
@@ -90,9 +91,10 @@
     gInputDeviceClassInfo.clazz = FindClassOrDie(env, "android/view/InputDevice");
     gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz);
 
-    gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
-                                                  "(IIILjava/lang/String;IILjava/lang/"
-                                                  "String;ZIILandroid/view/KeyCharacterMap;ZZZZ)V");
+    gInputDeviceClassInfo.ctor =
+            GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
+                             "(IIILjava/lang/String;IILjava/lang/"
+                             "String;ZIILandroid/view/KeyCharacterMap;ZZZZZ)V");
 
     gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz,
             "addMotionRange", "(IIFFFFF)V");
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 4ef63ae..05fcaec 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -27,6 +27,7 @@
 #include <android-base/chrono_utils.h>
 #include <android/graphics/region.h>
 #include <android/gui/BnScreenCaptureListener.h>
+#include <android/os/IInputConstants.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_hardware_HardwareBuffer.h>
 #include <android_runtime/android_view_Surface.h>
@@ -110,10 +111,12 @@
 static struct {
     jfieldID pixelFormat;
     jfieldID sourceCrop;
-    jfieldID frameScale;
+    jfieldID frameScaleX;
+    jfieldID frameScaleY;
     jfieldID captureSecureLayers;
     jfieldID allowProtected;
     jfieldID uid;
+    jfieldID grayscale;
 } gCaptureArgsClassInfo;
 
 static struct {
@@ -380,13 +383,17 @@
     captureArgs.sourceCrop =
             rectFromObj(env,
                         env->GetObjectField(captureArgsObject, gCaptureArgsClassInfo.sourceCrop));
-    captureArgs.frameScale =
-            env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScale);
+    captureArgs.frameScaleX =
+            env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScaleX);
+    captureArgs.frameScaleY =
+            env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScaleY);
     captureArgs.captureSecureLayers =
             env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.captureSecureLayers);
     captureArgs.allowProtected =
             env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.allowProtected);
     captureArgs.uid = env->GetLongField(captureArgsObject, gCaptureArgsClassInfo.uid);
+    captureArgs.grayscale =
+            env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.grayscale);
 }
 
 static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
@@ -1619,7 +1626,8 @@
                                         jlong frameTimelineVsyncId) {
     auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
 
-    transaction->setFrameTimelineVsync(frameTimelineVsyncId);
+    transaction->setFrameTimelineInfo(
+            {frameTimelineVsyncId, android::os::IInputConstants::INVALID_INPUT_EVENT_ID});
 }
 
 class JankDataListenerWrapper : public JankDataListener {
@@ -2032,12 +2040,14 @@
     gCaptureArgsClassInfo.pixelFormat = GetFieldIDOrDie(env, captureArgsClazz, "mPixelFormat", "I");
     gCaptureArgsClassInfo.sourceCrop =
             GetFieldIDOrDie(env, captureArgsClazz, "mSourceCrop", "Landroid/graphics/Rect;");
-    gCaptureArgsClassInfo.frameScale = GetFieldIDOrDie(env, captureArgsClazz, "mFrameScale", "F");
+    gCaptureArgsClassInfo.frameScaleX = GetFieldIDOrDie(env, captureArgsClazz, "mFrameScaleX", "F");
+    gCaptureArgsClassInfo.frameScaleY = GetFieldIDOrDie(env, captureArgsClazz, "mFrameScaleY", "F");
     gCaptureArgsClassInfo.captureSecureLayers =
             GetFieldIDOrDie(env, captureArgsClazz, "mCaptureSecureLayers", "Z");
     gCaptureArgsClassInfo.allowProtected =
             GetFieldIDOrDie(env, captureArgsClazz, "mAllowProtected", "Z");
     gCaptureArgsClassInfo.uid = GetFieldIDOrDie(env, captureArgsClazz, "mUid", "J");
+    gCaptureArgsClassInfo.grayscale = GetFieldIDOrDie(env, captureArgsClazz, "mGrayscale", "Z");
 
     jclass displayCaptureArgsClazz =
             FindClassOrDie(env, "android/view/SurfaceControl$DisplayCaptureArgs");
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c76a5d3..c5a9559 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -70,7 +70,6 @@
 #include <bionic/malloc.h>
 #include <bionic/mte.h>
 #include <cutils/fs.h>
-#include <cutils/memory.h>
 #include <cutils/multiuser.h>
 #include <cutils/sockets.h>
 #include <private/android_filesystem_config.h>
@@ -621,13 +620,6 @@
 
   // Set the jemalloc decay time to 1.
   mallopt(M_DECAY_TIME, 1);
-
-  // Avoid potentially expensive memory mitigations, mostly meant for system
-  // processes, in apps. These may cause app compat problems, use more memory,
-  // or reduce performance. While it would be nice to have them for apps,
-  // we will have to wait until they are proven out, have more efficient
-  // hardware, and/or apply them only to new applications.
-  process_disable_memory_mitigations();
 }
 
 static void SetUpSeccompFilter(uid_t uid, bool is_child_zygote) {
@@ -1785,6 +1777,14 @@
       break;
   }
   mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level);
+
+  // Avoid heap zero initialization for applications without MTE. Zero init may
+  // cause app compat problems, use more memory, or reduce performance. While it
+  // would be nice to have them for apps, we will have to wait until they are
+  // proven out, have more efficient hardware, and/or apply them only to new
+  // applications.
+  mallopt(M_BIONIC_ZERO_INIT, 0);
+
   // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART runtime.
   runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK;
 
diff --git a/core/tests/coretests/src/android/content/pm/SignatureTest.java b/core/tests/coretests/src/android/content/pm/SignatureTest.java
index f0b4af6..19458da 100644
--- a/core/tests/coretests/src/android/content/pm/SignatureTest.java
+++ b/core/tests/coretests/src/android/content/pm/SignatureTest.java
@@ -54,6 +54,32 @@
         assertFalse(Signature.areEffectiveMatch(asArray(A, M), asArray(A, B)));
     }
 
+    public void testHashCode_doesNotIncludeFlags() throws Exception {
+        // Some classes rely on the hash code not including the flags / capabilities for the signer
+        // to verify Set membership. This test verifies two signers with the same signature but
+        // different flags have the same hash code.
+        Signature signatureAWithAllCaps = new Signature(A.toCharsString());
+        // There are currently 5 capabilities that can be assigned to a previous signer, although
+        // for the purposes of this test all that matters is that the two flag values are distinct.
+        signatureAWithAllCaps.setFlags(31);
+        Signature signatureAWithNoCaps = new Signature(A.toCharsString());
+        signatureAWithNoCaps.setFlags(0);
+
+        assertEquals(signatureAWithAllCaps.hashCode(), signatureAWithNoCaps.hashCode());
+    }
+
+    public void testEquals_doesNotIncludeFlags() throws Exception {
+        // Similar to above some classes rely on equals only comparing the signature arrays
+        // for equality without including the flags. This test verifies two signers with the
+        // same signature but different flags are still considered equal.
+        Signature signatureAWithAllCaps = new Signature(A.toCharsString());
+        signatureAWithAllCaps.setFlags(31);
+        Signature signatureAWithNoCaps = new Signature(A.toCharsString());
+        signatureAWithNoCaps.setFlags(0);
+
+        assertEquals(signatureAWithAllCaps, signatureAWithNoCaps);
+    }
+
     private static Signature[] asArray(Signature... s) {
         return s;
     }
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
index b319886..341ee37 100644
--- a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
+++ b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
@@ -149,7 +149,7 @@
                 0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
                 0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */,
                 false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
-                true /* hasSensor */);
+                true /* hasSensor */, false /* hasBattery */);
         assertTrue(d.hasSensor());
         return d;
     }
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index 164bc86..75ac61a 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -363,6 +363,11 @@
             }
         }
 
+        if (response.iSecurityLevel == null) {
+            // This seems to be a pure certificate entry, nothing to return here.
+            return null;
+        }
+
         Integer keymasterAlgorithm = null;
         // We just need one digest for the algorithm name
         int keymasterDigest = -1;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 5e7f648..07169ce 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -490,7 +490,7 @@
             int[] keymasterEncryptionPaddings =
                     KeyProperties.EncryptionPadding.allToKeymaster(
                             spec.getEncryptionPaddings());
-            if (((spec.getPurposes() & KeyProperties.PURPOSE_DECRYPT) != 0)
+            if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0)
                     && (spec.isRandomizedEncryptionRequired())) {
                 for (int keymasterPadding : keymasterEncryptionPaddings) {
                     if (!KeymasterUtils
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 128d13c..bb67043 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -30,7 +30,6 @@
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
-import android.os.Handler;
 import android.provider.DeviceConfig;
 import android.util.Log;
 import android.util.Size;
@@ -847,11 +846,11 @@
                             && mPipBoundsState.getBounds().height()
                             < mPipBoundsState.getMaxSize().y;
                     if (toExpand) {
+                        mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
                         animateToMaximizedState(null);
                     } else {
-                        animateToMinimizedState();
+                        animateToUnexpandedState(getUserResizeBounds());
                     }
-                    mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
                 } else {
                     // Expand to fullscreen if this is a double tap
                     // the PiP should be frozen until the transition ends
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index eacabfd..633f21c 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -490,9 +490,11 @@
 
     if (mNativeSurface) {
         // TODO(b/165985262): measure performance impact
-        if (const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId);
-                vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) {
-            native_window_set_frame_timeline_vsync(mNativeSurface->getNativeWindow(), vsyncId);
+        const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId);
+        if (vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) {
+            const auto inputEventId = mCurrentFrameInfo->get(FrameInfoIndex::NewestInputEvent);
+            native_window_set_frame_timeline_info(mNativeSurface->getNativeWindow(), vsyncId,
+                                                  inputEventId);
         }
     }
 
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 9f327c9..51b685a 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -284,6 +284,12 @@
     /**
      * Configures the filter.
      *
+     * <p>Recofiguring must happen after stopping the filter.
+     *
+     * <p>When stopping, reconfiguring and restarting the filter, the client should discard all
+     * coming events until it receives {@link RestartEvent} through {@link FilterCallback} to avoid
+     * using the events from the previous configuration.
+     *
      * @param config the configuration of the filter.
      * @return result status of the operation.
      */
@@ -393,6 +399,10 @@
      *
      * <p>Does nothing if the filter is already started.
      *
+     * <p>When stopping, reconfiguring and restarting the filter, the client should discard all
+     * coming events until it receives {@link RestartEvent} through {@link FilterCallback} to avoid
+     * using the events from the previous configuration.
+     *
      * @return result status of the operation.
      */
     @Result
@@ -409,6 +419,12 @@
      *
      * <p>Does nothing if the filter is stopped or not started.
      *
+     * <p>Filter must be stopped to reconfigure.
+     *
+     * <p>When stopping, reconfiguring and restarting the filter, the client should discard all
+     * coming events until it receives {@link RestartEvent} through {@link FilterCallback} to avoid
+     * using the events from the previous configuration.
+     *
      * @return result status of the operation.
      */
     @Result
diff --git a/media/java/android/media/tv/tuner/filter/RestartEvent.java b/media/java/android/media/tv/tuner/filter/RestartEvent.java
index 0696301..9c5992a 100644
--- a/media/java/android/media/tv/tuner/filter/RestartEvent.java
+++ b/media/java/android/media/tv/tuner/filter/RestartEvent.java
@@ -19,17 +19,29 @@
 import android.annotation.SystemApi;
 
 /**
- * An Event that the client would reveice after stopping, reconfiguring and restarting a filter.
+ * An Event that the client would receive after starting a filter. This event is optional to be
+ * received on the newly opened and started filter. It must be received after stopping,
+ * reconfiguring and restarting a Filter to differentiate the valid reconfigured events from the
+ * previous events.
  *
  * <p>After stopping and restarting the filter, the client has to discard all coming events until
  * it receives {@link RestartEvent} to avoid using the events from the previous configuration.
  *
  * <p>Recofiguring must happen after stopping the filter.
  *
+ * @see Filter#stop()
+ * @see Filter#start()
+ * @see Filter#configure(FilterConfiguration)
+ *
  * @hide
  */
 @SystemApi
 public final class RestartEvent extends FilterEvent {
+    /**
+     * The stard id reserved for the newly opened filter's first start event.
+     */
+    public static final int NEW_FILTER_FIRST_START_ID = 0;
+
     private final int mStartId;
 
     // This constructor is used by JNI code only
@@ -38,13 +50,13 @@
     }
 
     /**
-     * Gets the start id.
+     * Gets the start id sent via the current Restart Event.
      *
-     * <p>An unique ID to mark the start point of receiving the valid filter events after
-     * reconfiguring. It must be sent at least once in the first event after the filter is
-     * restarted.
+     * <p>An unique ID to mark the start point of receiving the valid reconfigured filter events.
+     * The client must receive at least once after the filter is reconfigured and restarted.
      *
-     * <p>0 is reserved for the newly opened filter's first start. It's optional to be received.
+     * <p>{@link #NEW_FILTER_FIRST_START_ID} is reserved for the newly opened filter's first start.
+     * It's optional to be received.
      */
     public int getStartId() {
         return mStartId;
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
index c064de2..08a8d89 100644
--- a/media/jni/android_media_MediaMetricsJNI.cpp
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -18,7 +18,6 @@
 
 #include <binder/Parcel.h>
 #include <jni.h>
-#include <media/IMediaMetricsService.h>
 #include <media/MediaMetricsItem.h>
 #include <nativehelper/JNIHelp.h>
 #include <variant>
@@ -151,12 +150,7 @@
         return (jint)BAD_VALUE;
     }
 
-    sp<IMediaMetricsService> service = mediametrics::BaseItem::getService();
-    if (service == nullptr) {
-        ALOGW("Cannot retrieve mediametrics service");
-        return (jint)NO_INIT;
-    }
-    return (jint)service->submitBuffer((char *)buffer, length);
+    return (jint)mediametrics::BaseItem::submitBuffer((char *)buffer, length);
 }
 
 // Helper function to convert a native PersistableBundle to a Java
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java b/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java
new file mode 100644
index 0000000..9afa5d1
--- /dev/null
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.SystemApi;
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+
+/**
+ * Class for performing registration for all core connectivity services.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class ConnectivityFrameworkInitializer {
+    private ConnectivityFrameworkInitializer() {}
+
+    /**
+     * Called by {@link SystemServiceRegistry}'s static initializer and registers all core
+     * connectivity services to {@link Context}, so that {@link Context#getSystemService} can
+     * return them.
+     *
+     * @throws IllegalStateException if this is called anywhere besides
+     * {@link SystemServiceRegistry}.
+     */
+    public static void registerServiceWrappers() {
+        // registerContextAwareService will throw if this is called outside of SystemServiceRegistry
+        // initialization.
+        SystemServiceRegistry.registerContextAwareService(
+                Context.CONNECTIVITY_SERVICE,
+                ConnectivityManager.class,
+                (context, serviceBinder) -> {
+                    IConnectivityManager icm = IConnectivityManager.Stub.asInterface(serviceBinder);
+                    return new ConnectivityManager(context, icm);
+                }
+        );
+
+        // TODO: move outside of the connectivity JAR
+        SystemServiceRegistry.registerContextAwareService(
+                Context.VPN_MANAGEMENT_SERVICE,
+                VpnManager.class,
+                (context) -> {
+                    final ConnectivityManager cm = context.getSystemService(
+                            ConnectivityManager.class);
+                    return cm.createVpnManager();
+                }
+        );
+
+        SystemServiceRegistry.registerContextAwareService(
+                Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
+                ConnectivityDiagnosticsManager.class,
+                (context) -> {
+                    final ConnectivityManager cm = context.getSystemService(
+                            ConnectivityManager.class);
+                    return cm.createDiagnosticsManager();
+                }
+        );
+
+        SystemServiceRegistry.registerContextAwareService(
+                Context.TEST_NETWORK_SERVICE,
+                TestNetworkManager.class,
+                context -> {
+                    final ConnectivityManager cm = context.getSystemService(
+                            ConnectivityManager.class);
+                    return cm.startOrGetTestNetworkManager();
+                }
+        );
+    }
+}
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index ac8f9c9..2a0a74e 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -4823,6 +4823,28 @@
         }
     }
 
+    /** @hide */
+    public TestNetworkManager startOrGetTestNetworkManager() {
+        final IBinder tnBinder;
+        try {
+            tnBinder = mService.startOrGetTestNetworkService();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder));
+    }
+
+    /** @hide */
+    public VpnManager createVpnManager() {
+        return new VpnManager(mContext, mService);
+    }
+
+    /** @hide */
+    public ConnectivityDiagnosticsManager createDiagnosticsManager() {
+        return new ConnectivityDiagnosticsManager(mContext, mService);
+    }
+
     /**
      * Simulates a Data Stall for the specified Network.
      *
diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp
index c8f3bd3..8fc3181 100644
--- a/packages/Connectivity/service/Android.bp
+++ b/packages/Connectivity/service/Android.bp
@@ -57,6 +57,7 @@
     static_libs: [
         "net-utils-device-common",
         "net-utils-framework-common",
+        "netd-client",
     ],
     apex_available: [
         "//apex_available:platform",
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 5580afe..78282fb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -19,6 +19,7 @@
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
+import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
@@ -38,7 +39,9 @@
 import com.android.settingslib.R;
 import com.android.settingslib.Utils;
 
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Track status of Wi-Fi for the Sys UI.
@@ -50,6 +53,7 @@
     private final NetworkScoreManager mNetworkScoreManager;
     private final ConnectivityManager mConnectivityManager;
     private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private final Set<Integer> mNetworks = new HashSet<>();
     private final WifiNetworkScoreCache.CacheListener mCacheListener =
             new WifiNetworkScoreCache.CacheListener(mHandler) {
                 @Override
@@ -64,6 +68,20 @@
             .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
             .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build();
     private final NetworkCallback mNetworkCallback = new NetworkCallback() {
+        @Override
+        public void onAvailable(
+                Network network, NetworkCapabilities networkCapabilities,
+                LinkProperties linkProperties, boolean blocked) {
+            boolean isVcnOverWifi =
+                    networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+                            && (Utils.tryGetWifiInfoForVcn(networkCapabilities) != null);
+            boolean isWifi =
+                    networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+            if (isVcnOverWifi || isWifi) {
+                mNetworks.add(network.getNetId());
+            }
+        }
+
         // Note: onCapabilitiesChanged is guaranteed to be called "immediately" after onAvailable
         // and onLinkPropertiesChanged.
         @Override
@@ -84,9 +102,12 @@
 
         @Override
         public void onLost(Network network) {
-            updateWifiInfo(null);
-            updateStatusLabel();
-            mCallback.run();
+            if (mNetworks.contains(network.getNetId())) {
+                mNetworks.remove(network.getNetId());
+                updateWifiInfo(null);
+                updateStatusLabel();
+                mCallback.run();
+            }
         }
     };
     private final NetworkCallback mDefaultNetworkCallback = new NetworkCallback() {
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index efd941e..438cec8 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -272,6 +272,7 @@
                     Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
                     Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
                     Settings.Global.ENABLE_ADB_INCREMENTAL_INSTALL_DEFAULT,
+                    Settings.Global.ENABLE_MULTI_SLOT_TIMEOUT_MILLIS,
                     Settings.Global.ENHANCED_4G_MODE_ENABLED,
                     Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
                     Settings.Global.ERROR_LOGCAT_PREFIX,
@@ -280,6 +281,7 @@
                     Settings.Global.EUICC_UNSUPPORTED_COUNTRIES,
                     Settings.Global.EUICC_FACTORY_RESET_TIMEOUT_MILLIS,
                     Settings.Global.EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS,
+                    Settings.Global.EUICC_SWITCH_SLOT_TIMEOUT_MILLIS,
                     Settings.Global.FANCY_IME_ANIMATIONS,
                     Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
                     Settings.Global.FORCED_APP_STANDBY_ENABLED,
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 8c6aba2..01e54ff 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -33,4 +33,7 @@
     <bool name="flag_keyguard_layout">false</bool>
 
     <bool name="flag_brightness_slider">false</bool>
+
+    <!-- People Tile flag -->
+    <bool name="flag_conversations">false</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4baa06a..cb7327f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2556,8 +2556,8 @@
     <!-- Text for privacy dialog, indicating that the application is the enterprise version [CHAR LIMIT=NONE] -->
     <string name="ongoing_privacy_dialog_enterprise">(enterprise)</string>
 
-    <!-- Text for privacy dialog, identifying the phonecall app [CHAR LIMIT=NONE]-->
-    <string name="ongoing_privacy_dialog_phonecall">Phonecall</string>
+    <!-- Text for privacy dialog, identifying the phone call app [CHAR LIMIT=NONE]-->
+    <string name="ongoing_privacy_dialog_phonecall">Phone call</string>
 
     <!-- Text for privacy dialog, indicating that an app is using an op on behalf of another [CHAR LIMIT=NONE] -->
     <string name="ongoing_privacy_dialog_attribution_text">(through <xliff:g id="attribution" example="Special app">%s</xliff:g>)</string>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 036fcf3..78f7966 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -127,7 +127,7 @@
                     }
 
                     // If SHOW_PEOPLE_SPACE is true, enable People Space widget provider.
-                    // TODO(b/170396074): Remove this when we don't need a widget anymore.
+                    // TODO(b/170396074): Migrate to new feature flag (go/silk-flags-howto)
                     try {
                         int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
                                 Settings.Global.SHOW_PEOPLE_SPACE, 1);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index d6413ed..0a7eea4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -602,7 +602,7 @@
     private void runScrollCapture(ScrollCaptureClient.Connection connection) {
         cancelTimeout();
         ScrollCaptureController controller = new ScrollCaptureController(mContext, connection,
-                mMainExecutor, mBgExecutor, mImageExporter);
+                mMainExecutor, mBgExecutor, mImageExporter, mUiEventLogger);
         controller.attach(mWindow);
         controller.start(new TakeScreenshotService.RequestCallback() {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index f1fb688..5cf0188 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -63,7 +63,15 @@
     @UiEvent(doc = "screenshot swiped to dismiss")
     SCREENSHOT_SWIPE_DISMISSED(656),
     @UiEvent(doc = "screenshot reentered for new screenshot")
-    SCREENSHOT_REENTERED(640);
+    SCREENSHOT_REENTERED(640),
+    @UiEvent(doc = "Long screenshot button was shown to the user")
+    SCREENSHOT_LONG_SCREENSHOT_IMPRESSION(687),
+    @UiEvent(doc = "User has requested a long screenshot")
+    SCREENSHOT_LONG_SCREENSHOT_REQUESTED(688),
+    @UiEvent(doc = "User has shared a long screenshot")
+    SCREENSHOT_LONG_SCREENSHOT_SHARE(689),
+    @UiEvent(doc = "User has sent a long screenshot to the editor")
+    SCREENSHOT_LONG_SCREENSHOT_EDIT(690);
 
     private final int mId;
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index bf86b68..3bc5ebf 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -192,14 +192,14 @@
         if (DEBUG_SCROLL) {
             Log.d(TAG, "Showing Scroll option");
         }
+        mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_IMPRESSION);
         mScrollChip.setVisibility(VISIBLE);
         mScrollChip.setOnClickListener((v) -> {
             if (DEBUG_INPUT) {
                 Log.d(TAG, "scroll chip tapped");
             }
+            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_REQUESTED);
             onClick.run();
-            // TODO Logging, store event consumer to a field
-            //onElementTapped.accept(ScreenshotEvent.SCREENSHOT_SCROLL_TAPPED);
         });
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
index 9be3566..176a2c7 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
@@ -29,6 +29,7 @@
 import android.view.Window;
 import android.widget.ImageView;
 
+import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.screenshot.ScrollCaptureClient.Connection;
 import com.android.systemui.screenshot.ScrollCaptureClient.Session;
@@ -58,6 +59,7 @@
     private final Executor mBgExecutor;
     private final ImageExporter mImageExporter;
     private final ImageTileSet mImageTileSet;
+    private final UiEventLogger mUiEventLogger;
 
     private ZonedDateTime mCaptureTime;
     private UUID mRequestId;
@@ -72,12 +74,13 @@
     private Runnable mPendingAction;
 
     public ScrollCaptureController(Context context, Connection connection, Executor uiExecutor,
-            Executor bgExecutor, ImageExporter exporter) {
+            Executor bgExecutor, ImageExporter exporter, UiEventLogger uiEventLogger) {
         mContext = context;
         mConnection = connection;
         mUiExecutor = uiExecutor;
         mBgExecutor = bgExecutor;
         mImageExporter = exporter;
+        mUiEventLogger = uiEventLogger;
         mImageTileSet = new ImageTileSet();
     }
 
@@ -136,10 +139,12 @@
             disableButtons();
             finish();
         } else if (id == R.id.edit) {
+            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
             v.setPressed(true);
             disableButtons();
             edit();
         } else if (id == R.id.share) {
+            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE);
             v.setPressed(true);
             disableButtons();
             share();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index c54c459..e7b60c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -66,4 +66,8 @@
     public boolean useNewBrightnessSlider() {
         return mFlagReader.isEnabled(R.bool.flag_brightness_slider);
     }
+
+    public boolean isPeopleTileEnabled() {
+        return mFlagReader.isEnabled(R.bool.flag_conversations);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
index 4fde118..db49e44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
@@ -21,7 +21,6 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
@@ -50,7 +49,6 @@
     private final ShadeListBuilder mListBuilder;
     private final NotifCoordinators mNotifPluggableCoordinators;
     private final NotifInflaterImpl mNotifInflater;
-    private final PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
     private final DumpManager mDumpManager;
     private final ShadeViewManagerFactory mShadeViewManagerFactory;
     private final FeatureFlags mFeatureFlags;
@@ -64,7 +62,6 @@
             ShadeListBuilder listBuilder,
             NotifCoordinators notifCoordinators,
             NotifInflaterImpl notifInflater,
-            PeopleSpaceWidgetManager peopleSpaceWidgetManager,
             DumpManager dumpManager,
             ShadeViewManagerFactory shadeViewManagerFactory,
             FeatureFlags featureFlags) {
@@ -75,7 +72,6 @@
         mNotifPluggableCoordinators = notifCoordinators;
         mDumpManager = dumpManager;
         mNotifInflater = notifInflater;
-        mPeopleSpaceWidgetManager = peopleSpaceWidgetManager;
         mShadeViewManagerFactory = shadeViewManagerFactory;
         mFeatureFlags = featureFlags;
     }
@@ -103,7 +99,6 @@
         mListBuilder.attach(mNotifCollection);
         mNotifCollection.attach(mGroupCoalescer);
         mGroupCoalescer.attach(notificationService);
-        mPeopleSpaceWidgetManager.attach(notificationService);
 
         Log.d(TAG, "Notif pipeline initialized");
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 54ce4ed..0ad6507 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -18,6 +18,7 @@
 
 import android.service.notification.StatusBarNotification
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.people.widget.PeopleSpaceWidgetManager
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption
 import com.android.systemui.statusbar.FeatureFlags
 import com.android.systemui.statusbar.NotificationListener
@@ -73,7 +74,8 @@
     private val headsUpController: HeadsUpController,
     private val headsUpViewBinder: HeadsUpViewBinder,
     private val clickerBuilder: NotificationClicker.Builder,
-    private val animatedImageNotificationManager: AnimatedImageNotificationManager
+    private val animatedImageNotificationManager: AnimatedImageNotificationManager,
+    private val peopleSpaceWidgetManager: PeopleSpaceWidgetManager
 ) : NotificationsController {
 
     override fun initialize(
@@ -126,6 +128,10 @@
 
             entryManager.attach(notificationListener)
         }
+
+        if (featureFlags.isPeopleTileEnabled) {
+            peopleSpaceWidgetManager.attach(notificationListener)
+        }
     }
 
     override fun dump(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 5f90077..f6165f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -316,11 +316,23 @@
 
         mIconController.removeAllIconsForSlot(mSlotMobile);
         mMobileStates.clear();
+        List<NoCallingIconState> noCallingStates = new ArrayList<NoCallingIconState>();
+        noCallingStates.addAll(mNoCallingStates);
         mNoCallingStates.clear();
         final int n = subs.size();
         for (int i = 0; i < n; i++) {
             mMobileStates.add(new MobileIconState(subs.get(i).getSubscriptionId()));
-            mNoCallingStates.add(new NoCallingIconState(subs.get(i).getSubscriptionId()));
+            boolean isNewSub = true;
+            for (NoCallingIconState state : noCallingStates) {
+                if (state.subId == subs.get(i).getSubscriptionId()) {
+                    mNoCallingStates.add(state);
+                    isNewSub = false;
+                    break;
+                }
+            }
+            if (isNewSub) {
+                mNoCallingStates.add(new NoCallingIconState(subs.get(i).getSubscriptionId()));
+            }
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index da1f5d3..f8b6383 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -37,6 +37,7 @@
 import android.app.Instrumentation;
 import android.content.Intent;
 import android.net.ConnectivityManager;
+import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
@@ -343,6 +344,8 @@
         setConnectivityCommon(networkType, validated, isConnected);
         if (networkType == NetworkCapabilities.TRANSPORT_WIFI) {
             if (isConnected) {
+                mNetworkCallback.onAvailable(mock(Network.class),
+                        new NetworkCapabilities(mNetCapabilities), new LinkProperties(), false);
                 mNetworkCallback.onCapabilitiesChanged(
                         mock(Network.class), new NetworkCapabilities(mNetCapabilities));
             } else {
@@ -357,6 +360,8 @@
         setConnectivityCommon(networkType, validated, isConnected);
         if (networkType == NetworkCapabilities.TRANSPORT_CELLULAR) {
             if (isConnected) {
+                mNetworkCallback.onAvailable(mock(Network.class),
+                        new NetworkCapabilities(mNetCapabilities), new LinkProperties(), false);
                 mNetworkCallback.onCapabilitiesChanged(
                         mock(Network.class), new NetworkCapabilities(mNetCapabilities));
             } else {
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index ae024ff..5dd271c 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -260,6 +260,10 @@
     // Package: android
     NOTE_ADB_WIFI_ACTIVE = 62;
 
+    // Notify the user a carrier suggestion is available to get IMSI exemption.
+    // Package: android
+    NOTE_CARRIER_SUGGESTION_AVAILABLE = 63;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 4f0efb4..c091dfa 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -216,8 +216,6 @@
 import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.utils.PriorityDump;
 
-import com.google.android.collect.Lists;
-
 import libcore.io.IoUtils;
 
 import java.io.FileDescriptor;
@@ -1577,7 +1575,7 @@
     @Override
     public NetworkInfo[] getAllNetworkInfo() {
         enforceAccessPermission();
-        final ArrayList<NetworkInfo> result = Lists.newArrayList();
+        final ArrayList<NetworkInfo> result = new ArrayList<>();
         for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
                 networkType++) {
             NetworkInfo info = getNetworkInfo(networkType);
@@ -1851,7 +1849,7 @@
         // This contains IMSI details, so make sure the caller is privileged.
         NetworkStack.checkNetworkStackPermission(mContext);
 
-        final ArrayList<NetworkState> result = Lists.newArrayList();
+        final ArrayList<NetworkState> result = new ArrayList<>();
         for (Network network : getAllNetworks()) {
             final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
             if (nai != null) {
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 8b506ba..41903fc 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -372,10 +372,12 @@
      * even from a previous boot.
      */
     public void unregisterHealthObserver(PackageHealthObserver observer) {
-        synchronized (mLock) {
-            mAllObservers.remove(observer.getName());
-        }
-        syncState("unregistering observer: " + observer.getName());
+        mLongTaskHandler.post(() -> {
+            synchronized (mLock) {
+                mAllObservers.remove(observer.getName());
+            }
+            syncState("unregistering observer: " + observer.getName());
+        });
     }
 
     /**
@@ -982,7 +984,11 @@
                     if (!DeviceConfig.NAMESPACE_ROLLBACK.equals(properties.getNamespace())) {
                         return;
                     }
-                    updateConfigs();
+                    try {
+                        updateConfigs();
+                    } catch (Exception ignore) {
+                        Slog.w(TAG, "Failed to reload device config changes");
+                    }
                 });
     }
 
@@ -990,7 +996,8 @@
      * Health check is enabled or disabled after reading the flags
      * from DeviceConfig.
      */
-    private void updateConfigs() {
+    @VisibleForTesting
+    void updateConfigs() {
         synchronized (mLock) {
             mTriggerFailureCount = DeviceConfig.getInt(
                     DeviceConfig.NAMESPACE_ROLLBACK,
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index a08d066..e96fd39 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -32,6 +32,7 @@
 import android.net.NetworkAgentConfig;
 import android.net.NetworkCapabilities;
 import android.net.NetworkProvider;
+import android.net.NetworkStack;
 import android.net.RouteInfo;
 import android.net.StringNetworkSpecifier;
 import android.net.TestNetworkInterface;
@@ -48,6 +49,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.NetdUtils;
 
 import java.io.UncheckedIOException;
 import java.net.Inet4Address;
@@ -317,10 +319,10 @@
         }
 
         try {
-            // This requires NETWORK_STACK privileges.
             final long token = Binder.clearCallingIdentity();
             try {
-                mNMS.setInterfaceUp(iface);
+                NetworkStack.checkNetworkStackPermission(mContext);
+                NetdUtils.setInterfaceUp(mNetd, iface);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index d63a6c3..5b50431 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -111,7 +111,6 @@
     };
 
     public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList(
-            "android.hardware.audio@2.0::IDevicesFactory",
             "android.hardware.audio@4.0::IDevicesFactory",
             "android.hardware.audio@5.0::IDevicesFactory",
             "android.hardware.audio@6.0::IDevicesFactory",
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 0c8172d..6216fc0 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2815,12 +2815,24 @@
             r = smap.mServicesByIntent.get(filter);
             if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by intent: " + r);
         }
-        if (r != null && (r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0
-                && !callingPackage.equals(r.packageName)) {
-            // If an external service is running within its own package, other packages
-            // should not bind to that instance.
-            r = null;
-            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Whoops, can't use existing external service");
+        if (r != null) {
+            // Compared to resolveService below, the ServiceRecord here is retrieved from
+            // ServiceMap so the package visibility doesn't apply to it. We need to filter it.
+            if (mAm.getPackageManagerInternal().filterAppAccess(r.packageName, callingUid,
+                    userId)) {
+                Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId
+                        + ": not found");
+                return null;
+            }
+            if ((r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0
+                    && !callingPackage.equals(r.packageName)) {
+                // If an external service is running within its own package, other packages
+                // should not bind to that instance.
+                r = null;
+                if (DEBUG_SERVICE) {
+                    Slog.v(TAG_SERVICE, "Whoops, can't use existing external service");
+                }
+            }
         }
         if (r == null) {
             try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b8940c5..c8f5f8e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4509,7 +4509,6 @@
                                 String data, Bundle extras, boolean ordered,
                                 boolean sticky, int sendingUser) {
                             synchronized (ActivityManagerService.this) {
-                                mOomAdjuster.mCachedAppOptimizer.compactAllSystem();
                                 mAppProfiler.requestPssAllProcsLocked(
                                         SystemClock.uptimeMillis(), true, false);
                             }
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 27a238d..c558b3d 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -741,10 +741,12 @@
 
     // This will ensure app will be out of the freezer for at least FREEZE_TIMEOUT_MS
     void unfreezeTemporarily(ProcessRecord app) {
-        synchronized (mAm) {
-            if (app.frozen) {
-                unfreezeAppLocked(app);
-                freezeAppAsync(app);
+        if (mUseFreezer) {
+            synchronized (mAm) {
+                if (app.frozen) {
+                    unfreezeAppLocked(app);
+                    freezeAppAsync(app);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index a768532..bbf927b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -4447,7 +4447,7 @@
             }
 
             app.getPkgList().forEachPackage(packageName -> {
-                if (updateFrameworkRes && packagesToUpdate.contains(packageName)) {
+                if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
                     try {
                         final ApplicationInfo ai = AppGlobals.getPackageManager()
                                 .getApplicationInfo(packageName, STOCK_PM_FLAGS, app.userId);
diff --git a/services/core/java/com/android/server/am/ProcessProfileRecord.java b/services/core/java/com/android/server/am/ProcessProfileRecord.java
index cf309f4..9fd2bd7 100644
--- a/services/core/java/com/android/server/am/ProcessProfileRecord.java
+++ b/services/core/java/com/android/server/am/ProcessProfileRecord.java
@@ -623,6 +623,8 @@
             DebugUtils.printSizeValue(pw, mLastCachedSwapPss * 1024);
             pw.print(" lastRss=");
             DebugUtils.printSizeValue(pw, mLastRss * 1024);
+            pw.println();
+            pw.print(prefix);
             pw.print(" trimMemoryLevel=");
             pw.println(mTrimMemoryLevel);
             pw.println();
diff --git a/services/core/java/com/android/server/graphics/fonts/FontCrashDetector.java b/services/core/java/com/android/server/graphics/fonts/FontCrashDetector.java
new file mode 100644
index 0000000..b082b25
--- /dev/null
+++ b/services/core/java/com/android/server/graphics/fonts/FontCrashDetector.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * A class to detect font-related native crash.
+ *
+ * <p>If a fs-verity protected file is accessed through mmap and corrupted file block is detected,
+ * SIGBUG signal is generated and the process will crash. To find corrupted files and remove them,
+ * we use a marker file to detect crash.
+ * <ol>
+ *     <li>Create a marker file before reading fs-verity protected font files.
+ *     <li>Delete the marker file after reading font files successfully.
+ *     <li>If the marker file is found in the next process startup, it means that the process
+ *         crashed before. We will delete font files to prevent crash loop.
+ * </ol>
+ *
+ * <p>Example usage:
+ * <pre>
+ *     FontCrashDetector detector = new FontCrashDetector(new File("/path/to/marker_file"));
+ *     if (detector.hasCrashed()) {
+ *         // Do cleanup
+ *     }
+ *     try (FontCrashDetector.MonitoredBlock b = detector.start()) {
+ *         // Read files
+ *     }
+ * </pre>
+ *
+ * <p>This class DOES NOT detect Java exceptions. If a Java exception is thrown while monitoring
+ * crash, the marker file will be deleted. Creating and deleting marker files are not lightweight.
+ * Please use this class sparingly with caution.
+ */
+/* package */ final class FontCrashDetector {
+
+    private static final String TAG = "FontCrashDetector";
+
+    @NonNull
+    private final File mMarkerFile;
+
+    /* package */ FontCrashDetector(@NonNull File markerFile) {
+        mMarkerFile = markerFile;
+    }
+
+    /* package */ boolean hasCrashed() {
+        return mMarkerFile.exists();
+    }
+
+    /* package */ void clear() {
+        if (!mMarkerFile.delete()) {
+            Slog.e(TAG, "Could not delete marker file: " + mMarkerFile);
+        }
+    }
+
+    /** Starts crash monitoring. */
+    /* package */ MonitoredBlock start() {
+        try {
+            mMarkerFile.createNewFile();
+        } catch (IOException e) {
+            Slog.e(TAG, "Could not create marker file: " + mMarkerFile, e);
+        }
+        return new MonitoredBlock();
+    }
+
+    /** A helper class to monitor crash with try-with-resources syntax. */
+    /* package */ class MonitoredBlock implements AutoCloseable {
+        /** Ends crash monitoring. */
+        @Override
+        public void close() {
+            clear();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
index 7461405..8e5215b 100644
--- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
@@ -64,6 +64,7 @@
     private static final String TAG = "FontManagerService";
 
     private static final String FONT_FILES_DIR = "/data/fonts/files";
+    private static final String CRASH_MARKER_FILE = "/data/fonts/config/crash.txt";
 
     @Override
     public FontConfig getFontConfig() throws RemoteException {
@@ -179,6 +180,13 @@
         }
     }
 
+    @NonNull
+    private final Context mContext;
+
+    @GuardedBy("FontManagerService.this")
+    @NonNull
+    private final FontCrashDetector mFontCrashDetector;
+
     @Nullable
     private final UpdatableFontDir mUpdatableFontDir;
 
@@ -188,7 +196,9 @@
 
     private FontManagerService(Context context) {
         mContext = context;
+        mFontCrashDetector = new FontCrashDetector(new File(CRASH_MARKER_FILE));
         mUpdatableFontDir = createUpdatableFontDir();
+        initialize();
     }
 
     @Nullable
@@ -201,20 +211,35 @@
                 new OtfFontFileParser(), new FsverityUtilImpl());
     }
 
-
-    @NonNull
-    private final Context mContext;
+    private void initialize() {
+        synchronized (FontManagerService.this) {
+            if (mUpdatableFontDir == null) {
+                mSerializedFontMap = buildNewSerializedFontMap();
+                return;
+            }
+            if (mFontCrashDetector.hasCrashed()) {
+                Slog.i(TAG, "Crash detected. Clearing font updates.");
+                try {
+                    mUpdatableFontDir.clearUpdates();
+                } catch (SystemFontException e) {
+                    Slog.e(TAG, "Failed to clear updates.", e);
+                }
+                mFontCrashDetector.clear();
+            }
+            try (FontCrashDetector.MonitoredBlock ignored = mFontCrashDetector.start()) {
+                mUpdatableFontDir.loadFontFileMap();
+                mSerializedFontMap = buildNewSerializedFontMap();
+            }
+        }
+    }
 
     @NonNull
     public Context getContext() {
         return mContext;
     }
 
-    @NonNull /* package */ SharedMemory getCurrentFontMap() {
+    @Nullable /* package */ SharedMemory getCurrentFontMap() {
         synchronized (FontManagerService.this) {
-            if (mSerializedFontMap == null) {
-                mSerializedFontMap = buildNewSerializedFontMap();
-            }
             return mSerializedFontMap;
         }
     }
@@ -234,9 +259,10 @@
                         FontManager.RESULT_ERROR_VERSION_MISMATCH,
                         "The base config version is older than current.");
             }
-            mUpdatableFontDir.installFontFile(fd, pkcs7Signature);
-            // Create updated font map in the next getSerializedSystemFontMap() call.
-            mSerializedFontMap = null;
+            try (FontCrashDetector.MonitoredBlock ignored = mFontCrashDetector.start()) {
+                mUpdatableFontDir.installFontFile(fd, pkcs7Signature);
+                mSerializedFontMap = buildNewSerializedFontMap();
+            }
         }
     }
 
@@ -246,7 +272,12 @@
                     FontManager.RESULT_ERROR_FONT_UPDATER_DISABLED,
                     "The font updater is disabled.");
         }
-        mUpdatableFontDir.clearUpdates();
+        synchronized (FontManagerService.this) {
+            try (FontCrashDetector.MonitoredBlock ignored = mFontCrashDetector.start()) {
+                mUpdatableFontDir.clearUpdates();
+                mSerializedFontMap = buildNewSerializedFontMap();
+            }
+        }
     }
 
     /* package */ Map<String, File> getFontFileMap() {
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
index b0bc65b..0cb7045 100644
--- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -142,11 +142,9 @@
         mFsverityUtil = fsverityUtil;
         mConfigFile = configFile;
         mTmpConfigFile = new File(configFile.getAbsoluteFile() + ".tmp");
-        loadFontFileMap();
     }
 
-    private void loadFontFileMap() {
-        // TODO: SIGBUS crash protection
+    /* package */ void loadFontFileMap() {
         synchronized (UpdatableFontDir.this) {
             boolean success = false;
 
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index f6e08fb..2e4200c 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -289,6 +289,8 @@
     private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
     private static native boolean nativeIsVibrating(long ptr, int deviceId);
     private static native int[] nativeGetVibratorIds(long ptr, int deviceId);
+    private static native int nativeGetBatteryCapacity(long ptr, int deviceId);
+    private static native int nativeGetBatteryStatus(long ptr, int deviceId);
     private static native void nativeReloadKeyboardLayouts(long ptr);
     private static native void nativeReloadDeviceAliases(long ptr);
     private static native String nativeDump(long ptr);
@@ -2008,6 +2010,18 @@
 
     // Binder call
     @Override
+    public int getBatteryStatus(int deviceId) {
+        return nativeGetBatteryStatus(mPtr, deviceId);
+    }
+
+    // Binder call
+    @Override
+    public int getBatteryCapacity(int deviceId) {
+        return nativeGetBatteryCapacity(mPtr, deviceId);
+    }
+
+    // Binder call
+    @Override
     public void setPointerIconType(int iconId) {
         nativeSetPointerIconType(mPtr, iconId);
     }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 6308ace..e5b5350 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -4131,48 +4131,52 @@
     @BinderThread
     @Override
     @GuardedBy("mMethodMap")
-    public void startProtoDump(byte[] protoDump, int source, String where) {
-        if (protoDump == null && source != IME_TRACING_FROM_IMMS) {
-            // Dump not triggered from IMMS, but no proto information provided.
-            return;
-        }
-        ImeTracing tracingInstance = ImeTracing.getInstance();
-        if (!tracingInstance.isAvailable() || !tracingInstance.isEnabled()) {
-            return;
-        }
-
-        ProtoOutputStream proto = new ProtoOutputStream();
-        switch (source) {
-            case ImeTracing.IME_TRACING_FROM_CLIENT:
-                final long client_token = proto.start(InputMethodClientsTraceFileProto.ENTRY);
-                proto.write(InputMethodClientsTraceProto.ELAPSED_REALTIME_NANOS,
-                        SystemClock.elapsedRealtimeNanos());
-                proto.write(InputMethodClientsTraceProto.WHERE, where);
-                proto.write(InputMethodClientsTraceProto.CLIENT, protoDump);
-                proto.end(client_token);
-                break;
-            case ImeTracing.IME_TRACING_FROM_IMS:
-                final long service_token = proto.start(InputMethodServiceTraceFileProto.ENTRY);
-                proto.write(InputMethodServiceTraceProto.ELAPSED_REALTIME_NANOS,
-                        SystemClock.elapsedRealtimeNanos());
-                proto.write(InputMethodServiceTraceProto.WHERE, where);
-                proto.write(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE, protoDump);
-                proto.end(service_token);
-                break;
-            case IME_TRACING_FROM_IMMS:
-                final long managerservice_token =
-                        proto.start(InputMethodManagerServiceTraceFileProto.ENTRY);
-                proto.write(InputMethodManagerServiceTraceProto.ELAPSED_REALTIME_NANOS,
-                        SystemClock.elapsedRealtimeNanos());
-                proto.write(InputMethodManagerServiceTraceProto.WHERE, where);
-                dumpDebug(proto, InputMethodManagerServiceTraceProto.INPUT_METHOD_MANAGER_SERVICE);
-                proto.end(managerservice_token);
-                break;
-            default:
-                // Dump triggered by a source not recognised.
+    public void startProtoDump(byte[] protoDump, int source, String where,
+            IVoidResultCallback resultCallback) {
+        CallbackUtils.onResult(resultCallback, () -> {
+            if (protoDump == null && source != IME_TRACING_FROM_IMMS) {
+                // Dump not triggered from IMMS, but no proto information provided.
                 return;
-        }
-        tracingInstance.addToBuffer(proto, source);
+            }
+            ImeTracing tracingInstance = ImeTracing.getInstance();
+            if (!tracingInstance.isAvailable() || !tracingInstance.isEnabled()) {
+                return;
+            }
+
+            ProtoOutputStream proto = new ProtoOutputStream();
+            switch (source) {
+                case ImeTracing.IME_TRACING_FROM_CLIENT:
+                    final long client_token = proto.start(InputMethodClientsTraceFileProto.ENTRY);
+                    proto.write(InputMethodClientsTraceProto.ELAPSED_REALTIME_NANOS,
+                            SystemClock.elapsedRealtimeNanos());
+                    proto.write(InputMethodClientsTraceProto.WHERE, where);
+                    proto.write(InputMethodClientsTraceProto.CLIENT, protoDump);
+                    proto.end(client_token);
+                    break;
+                case ImeTracing.IME_TRACING_FROM_IMS:
+                    final long service_token = proto.start(InputMethodServiceTraceFileProto.ENTRY);
+                    proto.write(InputMethodServiceTraceProto.ELAPSED_REALTIME_NANOS,
+                            SystemClock.elapsedRealtimeNanos());
+                    proto.write(InputMethodServiceTraceProto.WHERE, where);
+                    proto.write(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE, protoDump);
+                    proto.end(service_token);
+                    break;
+                case IME_TRACING_FROM_IMMS:
+                    final long managerservice_token =
+                            proto.start(InputMethodManagerServiceTraceFileProto.ENTRY);
+                    proto.write(InputMethodManagerServiceTraceProto.ELAPSED_REALTIME_NANOS,
+                            SystemClock.elapsedRealtimeNanos());
+                    proto.write(InputMethodManagerServiceTraceProto.WHERE, where);
+                    dumpDebug(proto,
+                            InputMethodManagerServiceTraceProto.INPUT_METHOD_MANAGER_SERVICE);
+                    proto.end(managerservice_token);
+                    break;
+                default:
+                    // Dump triggered by a source not recognised.
+                    return;
+            }
+            tracingInstance.addToBuffer(proto, source);
+        });
     }
 
     @BinderThread
@@ -4183,40 +4187,44 @@
 
     @BinderThread
     @Override
-    public void startImeTrace() {
-        ImeTracing.getInstance().startTrace(null /* printwriter */);
-        ArrayMap<IBinder, ClientState> clients;
-        synchronized (mMethodMap) {
-            clients = new ArrayMap<>(mClients);
-        }
-        for (ClientState state : clients.values()) {
-            if (state != null) {
-                try {
-                    state.client.setImeTraceEnabled(true /* enabled */);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Error while trying to enable ime trace on client window", e);
+    public void startImeTrace(IVoidResultCallback resultCallback) {
+        CallbackUtils.onResult(resultCallback, () -> {
+            ImeTracing.getInstance().startTrace(null /* printwriter */);
+            ArrayMap<IBinder, ClientState> clients;
+            synchronized (mMethodMap) {
+                clients = new ArrayMap<>(mClients);
+            }
+            for (ClientState state : clients.values()) {
+                if (state != null) {
+                    try {
+                        state.client.setImeTraceEnabled(true /* enabled */);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Error while trying to enable ime trace on client window", e);
+                    }
                 }
             }
-        }
+        });
     }
 
     @BinderThread
     @Override
-    public void stopImeTrace() {
-        ImeTracing.getInstance().stopTrace(null /* printwriter */);
-        ArrayMap<IBinder, ClientState> clients;
-        synchronized (mMethodMap) {
-            clients = new ArrayMap<>(mClients);
-        }
-        for (ClientState state : clients.values()) {
-            if (state != null) {
-                try {
-                    state.client.setImeTraceEnabled(false /* enabled */);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Error while trying to disable ime trace on client window", e);
+    public void stopImeTrace(IVoidResultCallback resultCallback) {
+        CallbackUtils.onResult(resultCallback, () -> {
+            ImeTracing.getInstance().stopTrace(null /* printwriter */);
+            ArrayMap<IBinder, ClientState> clients;
+            synchronized (mMethodMap) {
+                clients = new ArrayMap<>(mClients);
+            }
+            for (ClientState state : clients.values()) {
+                if (state != null) {
+                    try {
+                        state.client.setImeTraceEnabled(false /* enabled */);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Error while trying to disable ime trace on client window", e);
+                    }
                 }
             }
-        }
+        });
     }
 
     @GuardedBy("mMethodMap")
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 7f9c766..6fec906 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1868,7 +1868,9 @@
 
         @BinderThread
         @Override
-        public void startProtoDump(byte[] clientProtoDump, int source, String where) {
+        public void startProtoDump(byte[] clientProtoDump, int source, String where,
+                IVoidResultCallback resultCallback) {
+            CallbackUtils.onResult(resultCallback, () -> { });
         }
 
         @BinderThread
@@ -1879,12 +1881,14 @@
 
         @BinderThread
         @Override
-        public void startImeTrace() {
+        public void startImeTrace(IVoidResultCallback resultCallback) {
+            CallbackUtils.onResult(resultCallback, () -> { });
         }
 
         @BinderThread
         @Override
-        public void stopImeTrace() {
+        public void stopImeTrace(IVoidResultCallback resultCallback) {
+            CallbackUtils.onResult(resultCallback, () -> { });
         }
     }
 }
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index dc1a26a..785e674 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location.contexthub;
 
+import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -320,6 +321,10 @@
             @Override
             public void onNanoAppDisabled(long nanoAppId) {
             }
+
+            @Override
+            public void onClientAuthorizationChanged(long nanoAppId, int authorization) {
+            }
         };
     }
 
@@ -697,6 +702,7 @@
      *
      * @param contextHubId   the ID of the hub this client is attached to
      * @param clientCallback the client interface to register with the service
+     * @param attributionTag an optional attribution tag within the given package
      * @return the generated client interface, null if registration was unsuccessful
      * @throws IllegalArgumentException if contextHubId is not a valid ID
      * @throws IllegalStateException    if max number of clients have already registered
@@ -704,7 +710,8 @@
      */
     @Override
     public IContextHubClient createClient(
-            int contextHubId, IContextHubClientCallback clientCallback) throws RemoteException {
+            int contextHubId, IContextHubClientCallback clientCallback,
+            @Nullable String attributionTag) throws RemoteException {
         checkPermissions();
         if (!isValidContextHubId(contextHubId)) {
             throw new IllegalArgumentException("Invalid context hub ID " + contextHubId);
@@ -723,13 +730,15 @@
      * @param contextHubId  the ID of the hub this client is attached to
      * @param pendingIntent the PendingIntent associated with this client
      * @param nanoAppId     the ID of the nanoapp PendingIntent events will be sent for
+     * @param attributionTag an optional attribution tag within the given package
      * @return the generated client interface
      * @throws IllegalArgumentException if hubInfo does not represent a valid hub
      * @throws IllegalStateException    if there were too many registered clients at the service
      */
     @Override
     public IContextHubClient createPendingIntentClient(
-            int contextHubId, PendingIntent pendingIntent, long nanoAppId) throws RemoteException {
+            int contextHubId, PendingIntent pendingIntent, long nanoAppId,
+            @Nullable String attributionTag) throws RemoteException {
         checkPermissions();
         if (!isValidContextHubId(contextHubId)) {
             throw new IllegalArgumentException("Invalid context hub ID " + contextHubId);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e32c00f..6843733 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -377,7 +377,8 @@
 
     static final String[] DEFAULT_ALLOWED_ADJUSTMENTS = new String[] {
             Adjustment.KEY_CONTEXTUAL_ACTIONS,
-            Adjustment.KEY_TEXT_REPLIES};
+            Adjustment.KEY_TEXT_REPLIES,
+            Adjustment.KEY_NOT_CONVERSATION};
 
     static final String[] NON_BLOCKABLE_DEFAULT_ROLES = new String[] {
             RoleManager.ROLE_DIALER,
@@ -2313,6 +2314,13 @@
                     } else if ("false".equals(value)) {
                         mAssistants.disallowAdjustmentType(Adjustment.KEY_RANKING_SCORE);
                     }
+                } else if (SystemUiDeviceConfigFlags.ENABLE_NAS_NOT_CONVERSATION.equals(name)) {
+                    String value = properties.getString(name, null);
+                    if ("true".equals(value)) {
+                        mAssistants.allowAdjustmentType(Adjustment.KEY_NOT_CONVERSATION);
+                    } else if ("false".equals(value)) {
+                        mAssistants.disallowAdjustmentType(Adjustment.KEY_NOT_CONVERSATION);
+                    }
                 }
             }
         };
@@ -9302,21 +9310,30 @@
                 Slog.v(TAG, "onNotificationEnqueuedLocked() called with: r = [" + r + "]");
             }
             final StatusBarNotification sbn = r.getSbn();
-            notifyAssistantLocked(
-                    sbn,
-                    r.getNotificationType(),
-                    true /* sameUserOnly */,
-                    (assistant, sbnHolder) -> {
-                        try {
-                            if (debug) {
-                                Slog.v(TAG,
-                                        "calling onNotificationEnqueuedWithChannel " + sbnHolder);
-                            }
-                            assistant.onNotificationEnqueuedWithChannel(sbnHolder, r.getChannel());
-                        } catch (RemoteException ex) {
-                            Slog.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex);
+
+            for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
+                boolean sbnVisible = isVisibleToListener(
+                        sbn, r.getNotificationType(), info)
+                        && info.isSameUser(r.getUserId());
+                if (sbnVisible) {
+                    TrimCache trimCache = new TrimCache(sbn);
+                    final INotificationListener assistant = (INotificationListener) info.service;
+                    final StatusBarNotification sbnToPost = trimCache.ForListener(info);
+                    final StatusBarNotificationHolder sbnHolder =
+                            new StatusBarNotificationHolder(sbnToPost);
+                    try {
+                        if (debug) {
+                            Slog.v(TAG,
+                                    "calling onNotificationEnqueuedWithChannel " + sbnHolder);
                         }
-                    });
+                        final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
+                        assistant.onNotificationEnqueuedWithChannel(sbnHolder, r.getChannel(),
+                                update);
+                    } catch (RemoteException ex) {
+                        Slog.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex);
+                    }
+                }
+            }
         }
 
         @GuardedBy("mNotificationLock")
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index f59934f..d7bc3bb 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -523,27 +523,39 @@
             if (VERBOSE) Slog.i(TAG, "Executing: validation for: " + mKey);
             long timeStartMs = System.currentTimeMillis();
             for (final String handle: mPendingLookups) {
+                final String cacheKey = getCacheKey(mContext.getUserId(), handle);
                 LookupResult lookupResult = null;
-                final Uri uri = Uri.parse(handle);
-                if ("tel".equals(uri.getScheme())) {
-                    if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle);
-                    lookupResult = resolvePhoneContact(mContext, uri.getSchemeSpecificPart());
-                } else if ("mailto".equals(uri.getScheme())) {
-                    if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle);
-                    lookupResult = resolveEmailContact(mContext, uri.getSchemeSpecificPart());
-                } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
-                    if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle);
-                    lookupResult = searchContacts(mContext, uri);
-                } else {
-                    lookupResult = new LookupResult();  // invalid person for the cache
-                    if (!"name".equals(uri.getScheme())) {
-                        Slog.w(TAG, "unsupported URI " + handle);
+                boolean cacheHit = false;
+                synchronized (mPeopleCache) {
+                    lookupResult = mPeopleCache.get(cacheKey);
+                    if (lookupResult != null && !lookupResult.isExpired()) {
+                        // The name wasn't already added to the cache, no need to retry
+                        cacheHit = true;
+                    }
+                }
+                if (!cacheHit) {
+                    final Uri uri = Uri.parse(handle);
+                    if ("tel".equals(uri.getScheme())) {
+                        if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle);
+                        lookupResult = resolvePhoneContact(mContext, uri.getSchemeSpecificPart());
+                    } else if ("mailto".equals(uri.getScheme())) {
+                        if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle);
+                        lookupResult = resolveEmailContact(mContext, uri.getSchemeSpecificPart());
+                    } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
+                        if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle);
+                        lookupResult = searchContacts(mContext, uri);
+                    } else {
+                        lookupResult = new LookupResult();  // invalid person for the cache
+                        if (!"name".equals(uri.getScheme())) {
+                            Slog.w(TAG, "unsupported URI " + handle);
+                        }
                     }
                 }
                 if (lookupResult != null) {
-                    synchronized (mPeopleCache) {
-                        final String cacheKey = getCacheKey(mContext.getUserId(), handle);
-                        mPeopleCache.put(cacheKey, lookupResult);
+                    if (!cacheHit) {
+                        synchronized (mPeopleCache) {
+                            mPeopleCache.put(cacheKey, lookupResult);
+                        }
                     }
                     if (DEBUG) {
                         Slog.d(TAG, "lookup contactAffinity is " + lookupResult.getAffinity());
@@ -580,4 +592,3 @@
         }
     }
 }
-
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index e0b57e4..402f646 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -118,8 +118,8 @@
         // Schedule a one-off job which scans installed packages and updates
         // out-of-date oat files.
         js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName)
-                    .setMinimumLatency(TimeUnit.MINUTES.toMillis(1))
-                    .setOverrideDeadline(TimeUnit.MINUTES.toMillis(1))
+                    .setMinimumLatency(TimeUnit.MINUTES.toMillis(10))
+                    .setOverrideDeadline(TimeUnit.MINUTES.toMillis(60))
                     .build());
 
         // Schedule a daily job which scans installed packages and compiles
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4ef892d..f68113d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -18819,9 +18819,11 @@
                     final VersionInfo versionInfo = request.versionInfos.get(installPackageName);
                     final boolean compareCompat = isCompatSignatureUpdateNeeded(versionInfo);
                     final boolean compareRecover = isRecoverSignatureUpdateNeeded(versionInfo);
+                    final boolean isRollback = installArgs != null
+                            && installArgs.installReason == PackageManager.INSTALL_REASON_ROLLBACK;
                     final boolean compatMatch = verifySignatures(signatureCheckPs,
                             disabledPkgSetting, parsedPackage.getSigningDetails(), compareCompat,
-                            compareRecover);
+                            compareRecover, isRollback);
                     // The new KeySets will be re-added later in the scanning process.
                     if (compatMatch) {
                         removeAppKeySetData = true;
@@ -19791,6 +19793,7 @@
         final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
         final boolean virtualPreload =
                 ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
+        final boolean isRollback = args.installReason == PackageManager.INSTALL_REASON_ROLLBACK;
         @ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
         if (args.move != null) {
             // moving a complete application; perform an initial scan on the new install location
@@ -19971,7 +19974,8 @@
                                 parsedPackage);
                         // We don't care about disabledPkgSetting on install for now.
                         final boolean compatMatch = verifySignatures(signatureCheckPs, null,
-                                parsedPackage.getSigningDetails(), compareCompat, compareRecover);
+                                parsedPackage.getSigningDetails(), compareCompat, compareRecover,
+                                isRollback);
                         // The new KeySets will be re-added later in the scanning process.
                         if (compatMatch) {
                             synchronized (mLock) {
@@ -20248,15 +20252,23 @@
                                             + pkgName11);
                         }
                     } else {
+                        SigningDetails parsedPkgSigningDetails = parsedPackage.getSigningDetails();
+                        SigningDetails oldPkgSigningDetails = oldPackage.getSigningDetails();
                         // default to original signature matching
-                        if (!parsedPackage.getSigningDetails().checkCapability(
-                                oldPackage.getSigningDetails(),
+                        if (!parsedPkgSigningDetails.checkCapability(oldPkgSigningDetails,
                                 SigningDetails.CertCapabilities.INSTALLED_DATA)
-                                && !oldPackage.getSigningDetails().checkCapability(
-                                parsedPackage.getSigningDetails(),
+                                && !oldPkgSigningDetails.checkCapability(parsedPkgSigningDetails,
                                 SigningDetails.CertCapabilities.ROLLBACK)) {
-                            throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
-                                    "New package has a different signature: " + pkgName11);
+                            // Allow the update to proceed if this is a rollback and the parsed
+                            // package's current signing key is the current signer or in the lineage
+                            // of the old package; this allows a rollback to a previously installed
+                            // version after an app's signing key has been rotated without requiring
+                            // the rollback capability on the previous signing key.
+                            if (!isRollback || !oldPkgSigningDetails.hasAncestorOrSelf(
+                                    parsedPkgSigningDetails)) {
+                                throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
+                                        "New package has a different signature: " + pkgName11);
+                            }
                         }
                     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index ee94b85..8015063 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -624,7 +624,7 @@
      */
     public static boolean verifySignatures(PackageSetting pkgSetting,
             PackageSetting disabledPkgSetting, PackageParser.SigningDetails parsedSignatures,
-            boolean compareCompat, boolean compareRecover)
+            boolean compareCompat, boolean compareRecover, boolean isRollback)
             throws PackageManagerException {
         final String packageName = pkgSetting.name;
         boolean compatMatch = false;
@@ -658,6 +658,13 @@
                 match = matchSignatureInSystem(pkgSetting, disabledPkgSetting);
             }
 
+            if (!match && isRollback) {
+                // Since a rollback can only be initiated for an APK previously installed on the
+                // device allow rolling back to a previous signing key even if the rollback
+                // capability has not been granted.
+                match = pkgSetting.signatures.mSigningDetails.hasAncestorOrSelf(parsedSignatures);
+            }
+
             if (!match) {
                 throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                         "Package " + packageName +
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index e12991a..9560f59 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -563,6 +563,7 @@
                 params.setRequestDowngrade(true);
                 params.setRequiredInstalledVersionCode(
                         pkgRollbackInfo.getVersionRolledBackFrom().getLongVersionCode());
+                params.setInstallReason(PackageManager.INSTALL_REASON_ROLLBACK);
                 if (isStaged()) {
                     params.setStaged();
                 }
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 9d21b92..132883e 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -168,8 +168,8 @@
             @NonNull NetworkRequest request, int score, int providerId) {
         if (score > getNetworkScore()) {
             Slog.v(getLogTag(),
-                    "Request " + request.requestId + " already satisfied by higher-scoring ("
-                            + score + ") network from provider " + providerId);
+                    "Request already satisfied by higher-scoring (" + score + ") network from "
+                            + "provider " + providerId + ": " + request);
             return;
         }
 
@@ -177,8 +177,7 @@
         for (VcnGatewayConnectionConfig gatewayConnectionConfig : mVcnGatewayConnections.keySet()) {
             if (requestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) {
                 Slog.v(getLogTag(),
-                        "Request " + request.requestId
-                                + " satisfied by existing VcnGatewayConnection");
+                        "Request already satisfied by existing VcnGatewayConnection: " + request);
                 return;
             }
         }
@@ -202,12 +201,12 @@
 
     private boolean requestSatisfiedByGatewayConnectionConfig(
             @NonNull NetworkRequest request, @NonNull VcnGatewayConnectionConfig config) {
-        final NetworkCapabilities configCaps = new NetworkCapabilities();
+        final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder();
         for (int cap : config.getAllExposedCapabilities()) {
-            configCaps.addCapability(cap);
+            builder.addCapability(cap);
         }
 
-        return request.networkCapabilities.satisfiedByNetworkCapabilities(configCaps);
+        return request.canBeSatisfiedBy(builder.build());
     }
 
     private String getLogTag() {
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 703bfab..3cfa00e 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -963,18 +963,18 @@
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     static NetworkCapabilities buildNetworkCapabilities(
             @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) {
-        final NetworkCapabilities caps = new NetworkCapabilities();
+        final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder();
 
-        caps.addTransportType(TRANSPORT_CELLULAR);
-        caps.addCapability(NET_CAPABILITY_NOT_CONGESTED);
-        caps.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        builder.addTransportType(TRANSPORT_CELLULAR);
+        builder.addCapability(NET_CAPABILITY_NOT_CONGESTED);
+        builder.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
 
         // Add exposed capabilities
         for (int cap : gatewayConnectionConfig.getAllExposedCapabilities()) {
-            caps.addCapability(cap);
+            builder.addCapability(cap);
         }
 
-        return caps;
+        return builder.build();
     }
 
     private static LinkProperties buildConnectedLinkProperties(
diff --git a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java
index 7f5b23c..b9babae 100644
--- a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java
+++ b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java
@@ -21,9 +21,9 @@
 import android.net.NetworkProvider;
 import android.net.NetworkRequest;
 import android.os.Looper;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
-import android.util.SparseArray;
 
 import java.util.Objects;
 import java.util.Set;
@@ -40,7 +40,13 @@
     private static final String TAG = VcnNetworkProvider.class.getSimpleName();
 
     private final Set<NetworkRequestListener> mListeners = new ArraySet<>();
-    private final SparseArray<NetworkRequestEntry> mRequests = new SparseArray<>();
+
+    /**
+     * Cache of NetworkRequest(s), scores and network providers, keyed by NetworkRequest
+     *
+     * <p>NetworkRequests are immutable once created, and therefore can be used as stable keys.
+     */
+    private final ArrayMap<NetworkRequest, NetworkRequestEntry> mRequests = new ArrayMap<>();
 
     public VcnNetworkProvider(Context context, Looper looper) {
         super(context, looper, VcnNetworkProvider.class.getSimpleName());
@@ -51,8 +57,8 @@
         mListeners.add(listener);
 
         // Send listener all cached requests
-        for (int i = 0; i < mRequests.size(); i++) {
-            notifyListenerForEvent(listener, mRequests.valueAt(i));
+        for (NetworkRequestEntry entry : mRequests.values()) {
+            notifyListenerForEvent(listener, entry);
         }
     }
 
@@ -75,7 +81,9 @@
                         request, score, providerId));
 
         final NetworkRequestEntry entry = new NetworkRequestEntry(request, score, providerId);
-        mRequests.put(request.requestId, entry);
+
+        // NetworkRequests are immutable once created, and therefore can be used as stable keys.
+        mRequests.put(request, entry);
 
         // TODO(b/176939047): Intelligently route requests to prioritized VcnInstances (based on
         // Default Data Sub, or similar)
@@ -86,7 +94,7 @@
 
     @Override
     public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {
-        mRequests.remove(request.requestId);
+        mRequests.remove(request);
     }
 
     private static class NetworkRequestEntry {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 11cc2c6..d5d06f9 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -670,8 +670,9 @@
     // Used in updating override configurations
     private final Configuration mTempConfig = new Configuration();
 
-    // Used in performing layout
-    private boolean mTmpWindowsBehindIme;
+    // Used in performing layout, to record the insets provided by other windows above the current
+    // window.
+    private InsetsState mTmpAboveInsetsState = new InsetsState();
 
     /**
      * Used to prevent recursions when calling
@@ -770,17 +771,11 @@
                     + " parentHidden=" + w.isParentWindowHidden());
         }
 
-        // Sets mBehindIme for each window. Windows behind IME can get IME insets.
-        if (w.mBehindIme != mTmpWindowsBehindIme) {
-            w.mBehindIme = mTmpWindowsBehindIme;
-            if (getInsetsStateController().getRawInsetsState().getSourceOrDefaultVisibility(
-                    ITYPE_IME)) {
-                // If IME is invisible, behind IME or not doesn't make the insets different.
-                mWinInsetsChanged.add(w);
-            }
-        }
-        if (w == mInputMethodWindow) {
-            mTmpWindowsBehindIme = true;
+        // Sets mAboveInsets for each window. Windows behind the window providing the insets can
+        // receive the insets.
+        if (!w.mAboveInsetsState.equals(mTmpAboveInsetsState)) {
+            w.mAboveInsetsState.set(mTmpAboveInsetsState);
+            mWinInsetsChanged.add(w);
         }
 
         // If this view is GONE, then skip it -- keep the current frame, and let the caller know
@@ -816,8 +811,16 @@
                     + " mContainingFrame=" + w.getContainingFrame()
                     + " mDisplayFrame=" + w.getDisplayFrame());
         }
+        provideInsetsByWindow(w);
     };
 
+    private void provideInsetsByWindow(WindowState w) {
+        for (int i = 0; i < w.mProvidedInsetsSources.size(); i++) {
+            final InsetsSource providedSource = w.mProvidedInsetsSources.valueAt(i);
+            mTmpAboveInsetsState.addSource(providedSource);
+        }
+    }
+
     private final Consumer<WindowState> mPerformLayoutAttached = w -> {
         if (w.mLayoutAttached) {
             if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
@@ -4283,14 +4286,20 @@
                     + " dh=" + mDisplayInfo.logicalHeight);
         }
 
+        // Used to indicate that we have processed the insets windows. This needs to be after
+        // beginLayoutLw to ensure the raw insets state display related info is initialized.
+        final InsetsState rawInsetsState = getInsetsStateController().getRawInsetsState();
+        mTmpAboveInsetsState = new InsetsState();
+        mTmpAboveInsetsState.setDisplayFrame(rawInsetsState.getDisplayFrame());
+        mTmpAboveInsetsState.setDisplayCutout(rawInsetsState.getDisplayCutout());
+        mTmpAboveInsetsState.mirrorAlwaysVisibleInsetsSources(rawInsetsState);
+
         int seq = mLayoutSeq + 1;
         if (seq < 0) seq = 0;
         mLayoutSeq = seq;
 
         mTmpInitial = initial;
 
-        // Used to indicate that we have processed the IME window.
-        mTmpWindowsBehindIme = false;
 
         // First perform layout of any root windows (not attached to another window).
         forAllWindows(mPerformLayout, true /* traverseTopToBottom */);
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 1692df6..c6c7fe0 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -151,6 +151,7 @@
             // animate-out as new one animates-in.
             mWin.cancelAnimation();
             mWin.mPendingPositionChanged = null;
+            mWin.mProvidedInsetsSources.remove(mSource.getType());
         }
         ProtoLog.d(WM_DEBUG_IME, "InsetsSource setWin %s", win);
         mWin = win;
@@ -160,11 +161,14 @@
             setServerVisible(false);
             mSource.setFrame(new Rect());
             mSource.setVisibleFrame(null);
-        } else if (mControllable) {
-            mWin.setControllableInsetProvider(this);
-            if (mPendingControlTarget != null) {
-                updateControlForTarget(mPendingControlTarget, true /* force */);
-                mPendingControlTarget = null;
+        } else {
+            mWin.mProvidedInsetsSources.put(mSource.getType(), mSource);
+            if (mControllable) {
+                mWin.setControllableInsetProvider(this);
+                if (mPendingControlTarget != null) {
+                    updateControlForTarget(mPendingControlTarget, true /* force */);
+                    mPendingControlTarget = null;
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 267f677..3ba7b7d 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -104,6 +104,8 @@
      * visible to the target. e.g., the source which represents the target window itself, and the
      * IME source when the target is above IME. We also need to exclude certain types of insets
      * source for client within specific windowing modes.
+     * This is to get the insets for a window layout on the screen. If the window is not there, use
+     * the {@link #getInsetsForWindowMetrics} to get insets instead.
      *
      * @param target The window associate with the perspective.
      * @return The state stripped of the necessary information.
@@ -117,8 +119,8 @@
         final @InternalInsetsType int type = provider != null
                 ? provider.getSource().getType() : ITYPE_INVALID;
         return getInsetsForTarget(type, target.getWindowingMode(), target.isAlwaysOnTop(),
-                isAboveIme(target),
-                target.getFrozenInsetsState() != null ? target.getFrozenInsetsState() : mState);
+                target.getFrozenInsetsState() != null ? target.getFrozenInsetsState() :
+                target.mAboveInsetsState);
     }
 
     InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
@@ -133,19 +135,7 @@
         final @WindowingMode int windowingMode = token != null
                 ? token.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
         final boolean alwaysOnTop = token != null && token.isAlwaysOnTop();
-        return getInsetsForTarget(type, windowingMode, alwaysOnTop, isAboveIme(token), mState);
-    }
-
-    private boolean isAboveIme(WindowContainer target) {
-        final WindowState imeWindow = mDisplayContent.mInputMethodWindow;
-        if (target == null || imeWindow == null) {
-            return false;
-        }
-        if (target instanceof WindowState) {
-            final WindowState win = (WindowState) target;
-            return win.needsRelativeLayeringToIme() || !win.mBehindIme;
-        }
-        return false;
+        return getInsetsForTarget(type, windowingMode, alwaysOnTop, mState);
     }
 
     private static @InternalInsetsType
@@ -181,10 +171,12 @@
      * @see #getInsetsForWindowMetrics
      */
     private InsetsState getInsetsForTarget(@InternalInsetsType int type,
-            @WindowingMode int windowingMode, boolean isAlwaysOnTop, boolean aboveIme,
-            @NonNull InsetsState state) {
+            @WindowingMode int windowingMode, boolean isAlwaysOnTop, InsetsState state) {
+        boolean stateCopied = false;
+
         if (type != ITYPE_INVALID) {
             state = new InsetsState(state);
+            stateCopied = true;
             state.removeSource(type);
 
             // Navigation bar doesn't get influenced by anything else
@@ -219,23 +211,15 @@
 
         if (WindowConfiguration.isFloating(windowingMode)
                 || (windowingMode == WINDOWING_MODE_MULTI_WINDOW && isAlwaysOnTop)) {
-            state = new InsetsState(state);
+            if (!stateCopied) {
+                state = new InsetsState(state);
+                stateCopied = true;
+            }
             state.removeSource(ITYPE_STATUS_BAR);
             state.removeSource(ITYPE_NAVIGATION_BAR);
             state.removeSource(ITYPE_EXTRA_NAVIGATION_BAR);
         }
 
-        if (aboveIme) {
-            InsetsSource imeSource = state.peekSource(ITYPE_IME);
-            if (imeSource != null && imeSource.isVisible()) {
-                imeSource = new InsetsSource(imeSource);
-                imeSource.setVisible(false);
-                imeSource.setFrame(0, 0, 0, 0);
-                state = new InsetsState(state);
-                state.addSource(imeSource);
-            }
-        }
-
         return state;
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 1597604..f2be5ff 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -212,6 +212,7 @@
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.MergedConfiguration;
@@ -647,9 +648,14 @@
     boolean mSeamlesslyRotated = false;
 
     /**
-     * Indicates if this window is behind IME. Only windows behind IME can get insets from IME.
+     * The insets state of sources provided by windows above the current window.
      */
-    boolean mBehindIme = false;
+    InsetsState mAboveInsetsState = new InsetsState();
+
+    /**
+     * The insets sources provided by this window.
+     */
+    ArrayMap<Integer, InsetsSource> mProvidedInsetsSources = new ArrayMap<>();
 
     /**
      * Surface insets from the previous call to relayout(), used to track
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index dc15b07..5b587e9 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -26,14 +26,14 @@
 // Log debug messages about InputDispatcherPolicy
 #define DEBUG_INPUT_DISPATCHER_POLICY 0
 
-
-#include <atomic>
-#include <cinttypes>
-#include <limits.h>
 #include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
+#include <android/os/IInputConstants.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
+#include <limits.h>
+#include <atomic>
+#include <cinttypes>
 
 #include <utils/Log.h>
 #include <utils/Looper.h>
@@ -46,6 +46,7 @@
 #include <input/SpriteController.h>
 #include <ui/Region.h>
 
+#include <batteryservice/include/batteryservice/BatteryServiceConstants.h>
 #include <inputflinger/InputManager.h>
 
 #include <android_os_MessageQueue.h>
@@ -1908,6 +1909,20 @@
     return vibIdArray;
 }
 
+static jint nativeGetBatteryCapacity(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    std::optional<int32_t> ret = im->getInputManager()->getReader()->getBatteryCapacity(deviceId);
+    return static_cast<jint>(ret.value_or(android::os::IInputConstants::INVALID_BATTERY_CAPACITY));
+}
+
+static jint nativeGetBatteryStatus(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    std::optional<int32_t> ret = im->getInputManager()->getReader()->getBatteryStatus(deviceId);
+    return static_cast<jint>(ret.value_or(BATTERY_STATUS_UNKNOWN));
+}
+
 static void nativeReloadKeyboardLayouts(JNIEnv* /* env */,
         jclass /* clazz */, jlong ptr) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -2163,6 +2178,8 @@
         {"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate},
         {"nativeIsVibrating", "(JI)Z", (void*)nativeIsVibrating},
         {"nativeGetVibratorIds", "(JI)[I", (void*)nativeGetVibratorIds},
+        {"nativeGetBatteryCapacity", "(JI)I", (void*)nativeGetBatteryCapacity},
+        {"nativeGetBatteryStatus", "(JI)I", (void*)nativeGetBatteryStatus},
         {"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts},
         {"nativeReloadDeviceAliases", "(J)V", (void*)nativeReloadDeviceAliases},
         {"nativeDump", "(J)Ljava/lang/String;", (void*)nativeDump},
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index 9a9a171..444f9c6 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -264,7 +264,8 @@
         return new ConversationChannel(shortcutInfo, uid, parentChannel,
                 parentChannelGroup,
                 conversationInfo.getLastEventTimestamp(),
-                hasActiveNotifications(packageName, userId, shortcutId));
+                hasActiveNotifications(packageName, userId, shortcutId), false,
+                getStatuses(conversationInfo));
     }
 
     /** Returns the cached non-customized recent conversations. */
@@ -404,6 +405,10 @@
             String conversationId) {
         ConversationStore cs = getConversationStoreOrThrow(packageName, userId);
         ConversationInfo conversationInfo = getConversationInfoOrThrow(cs, conversationId);
+        return getStatuses(conversationInfo);
+    }
+
+    private @NonNull List<ConversationStatus> getStatuses(ConversationInfo conversationInfo) {
         Collection<ConversationStatus> statuses = conversationInfo.getStatuses();
         if (statuses != null) {
             final ArrayList<ConversationStatus> list = new ArrayList<>(statuses.size());
diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
index 743848c..2932926 100644
--- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
@@ -745,7 +745,8 @@
 
     private InputDevice createInputDeviceWithVibrator(int id) {
         return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
-                null, /* hasVibrator= */ true, false, false, false /* hasSensor */);
+                null, /* hasVibrator= */ true, false, false, false /* hasSensor */,
+                false /* hasBattery */);
     }
 
     private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/FontCrashDetectorTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/FontCrashDetectorTest.java
new file mode 100644
index 0000000..275e7c7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/FontCrashDetectorTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.graphics.fonts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.FileUtils;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class FontCrashDetectorTest {
+
+    private File mCacheDir;
+
+    @SuppressWarnings("ResultOfMethodCallIgnored")
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        mCacheDir = new File(context.getCacheDir(), "UpdatableFontDirTest");
+        FileUtils.deleteContentsAndDir(mCacheDir);
+        mCacheDir.mkdirs();
+    }
+
+    @Test
+    public void detectCrash() throws Exception {
+        // Prepare a marker file.
+        File file = new File(mCacheDir, "detectCrash");
+        assertThat(file.createNewFile()).isTrue();
+
+        FontCrashDetector detector = new FontCrashDetector(file);
+        assertThat(detector.hasCrashed()).isTrue();
+
+        detector.clear();
+        assertThat(detector.hasCrashed()).isFalse();
+        assertThat(file.exists()).isFalse();
+    }
+
+    @Test
+    public void monitorCrash() {
+        File file = new File(mCacheDir, "monitorCrash");
+        FontCrashDetector detector = new FontCrashDetector(file);
+        assertThat(detector.hasCrashed()).isFalse();
+
+        FontCrashDetector.MonitoredBlock block = detector.start();
+        assertThat(file.exists()).isTrue();
+
+        block.close();
+        assertThat(file.exists()).isFalse();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
index d067790..8331031 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -147,6 +147,7 @@
         UpdatableFontDir dirForPreparation = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dirForPreparation.loadFontFileMap();
         assertThat(dirForPreparation.getSystemFontConfig().getLastModifiedTimeMillis())
                 .isEqualTo(expectedModifiedDate);
         installFontFile(dirForPreparation, "foo,1", GOOD_SIGNATURE);
@@ -162,6 +163,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
         assertThat(dir.getFontFileMap()).containsKey("foo.ttf");
         assertThat(parser.getRevision(dir.getFontFileMap().get("foo.ttf"))).isEqualTo(3);
         assertThat(dir.getFontFileMap()).containsKey("bar.ttf");
@@ -177,6 +179,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
         assertThat(dir.getFontFileMap()).isEmpty();
     }
 
@@ -187,6 +190,7 @@
         UpdatableFontDir dirForPreparation = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dirForPreparation.loadFontFileMap();
         installFontFile(dirForPreparation, "foo,1", GOOD_SIGNATURE);
         installFontFile(dirForPreparation, "bar,2", GOOD_SIGNATURE);
         installFontFile(dirForPreparation, "foo,3", GOOD_SIGNATURE);
@@ -199,6 +203,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
         assertThat(dir.getFontFileMap()).isEmpty();
         // All font dirs (including dir for "bar.ttf") should be deleted.
         assertThat(mUpdatableFontFilesDir.list()).hasLength(0);
@@ -211,6 +216,7 @@
         UpdatableFontDir dirForPreparation = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dirForPreparation.loadFontFileMap();
         installFontFile(dirForPreparation, "foo,1", GOOD_SIGNATURE);
         installFontFile(dirForPreparation, "bar,2", GOOD_SIGNATURE);
         installFontFile(dirForPreparation, "foo,3", GOOD_SIGNATURE);
@@ -224,6 +230,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
         assertThat(dir.getFontFileMap()).isEmpty();
         // All font dirs (including dir for "bar.ttf") should be deleted.
         assertThat(mUpdatableFontFilesDir.list()).hasLength(0);
@@ -236,6 +243,7 @@
         UpdatableFontDir dirForPreparation = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dirForPreparation.loadFontFileMap();
         installFontFile(dirForPreparation, "foo,1", GOOD_SIGNATURE);
         installFontFile(dirForPreparation, "bar,2", GOOD_SIGNATURE);
         installFontFile(dirForPreparation, "foo,3", GOOD_SIGNATURE);
@@ -250,6 +258,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
         // For foo.ttf, preinstalled font (revision 5) should be used.
         assertThat(dir.getFontFileMap()).doesNotContainKey("foo.ttf");
         // For bar.ttf, updated font (revision 4) should be used.
@@ -268,6 +277,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 new File("/dev/null"));
+        dir.loadFontFileMap();
         assertThat(dir.getFontFileMap()).isEmpty();
     }
 
@@ -278,6 +288,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
 
         installFontFile(dir, "test,1", GOOD_SIGNATURE);
         assertThat(dir.getFontFileMap()).containsKey("test.ttf");
@@ -295,6 +306,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
 
         installFontFile(dir, "test,1", GOOD_SIGNATURE);
         Map<String, File> mapBeforeUpgrade = dir.getFontFileMap();
@@ -313,6 +325,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
 
         installFontFile(dir, "test,2", GOOD_SIGNATURE);
         try {
@@ -333,6 +346,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
 
         installFontFile(dir, "foo,1", GOOD_SIGNATURE);
         installFontFile(dir, "bar,2", GOOD_SIGNATURE);
@@ -349,6 +363,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
 
         try {
             installFontFile(dir, "test,1", "Invalid signature");
@@ -368,6 +383,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
 
         try {
             installFontFile(dir, "test,1", GOOD_SIGNATURE);
@@ -398,6 +414,7 @@
             UpdatableFontDir dir = new UpdatableFontDir(
                     mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                     readonlyFile);
+            dir.loadFontFileMap();
 
             try {
                 installFontFile(dir, "test,2", GOOD_SIGNATURE);
@@ -429,6 +446,7 @@
                         return 0;
                     }
                 }, fakeFsverityUtil, mConfigFile);
+        dir.loadFontFileMap();
 
         try {
             installFontFile(dir, "foo,1", GOOD_SIGNATURE);
@@ -456,6 +474,7 @@
                         return 0;
                     }
                 }, fakeFsverityUtil, mConfigFile);
+        dir.loadFontFileMap();
 
         try {
             installFontFile(dir, "foo,1", GOOD_SIGNATURE);
@@ -491,6 +510,7 @@
         UpdatableFontDir dir = new UpdatableFontDir(
                 mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                 mConfigFile);
+        dir.loadFontFileMap();
 
         try {
             installFontFile(dir, "foo,1", GOOD_SIGNATURE);
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 161d316..6e57896 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -535,8 +535,11 @@
         listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
                 mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
 
-        assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
-                TEST_SHORTCUT_ID)).isNotNull();
+        ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
+                TEST_SHORTCUT_ID);
+        assertThat(result).isNotNull();
+        assertThat(result.hasBirthdayToday()).isFalse();
+        assertThat(result.getStatuses()).isEmpty();
     }
 
     @Test
@@ -550,13 +553,15 @@
         shortcut.setCached(ShortcutInfo.FLAG_PINNED);
         mDataManager.addOrUpdateConversationInfo(shortcut);
         assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
-            TEST_SHORTCUT_ID)).isNotNull();
+                TEST_SHORTCUT_ID)).isNotNull();
         assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                 TEST_SHORTCUT_ID + "1")).isNull();
 
         NotificationListenerService listenerService =
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
         listenerService.onNotificationPosted(mStatusBarNotification);
+        ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build();
+        mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);
 
         ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
                 TEST_SHORTCUT_ID);
@@ -568,6 +573,8 @@
                 result.getParentNotificationChannel().getId());
         assertEquals(mStatusBarNotification.getPostTime(), result.getLastEventTimestamp());
         assertTrue(result.hasActiveNotifications());
+        assertFalse(result.hasBirthdayToday());
+        assertThat(result.getStatuses()).containsExactly(cs);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
index 28d313b..e71c2f5 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
@@ -294,6 +294,8 @@
 
     private InputDevice createInputDevice(int id, boolean hasVibrator) {
         return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
-                null, hasVibrator, false, false, false /* hasSensor */);
+                null, hasVibrator, false, false, false /* hasSensor */, false /* hasBattery */);
+
+
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 82ffa765..37fb0e9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -123,6 +123,15 @@
         updateDisplayFrames();
     }
 
+    void addWindowWithRawInsetsState(WindowState win) {
+        addWindow(win);
+        // Without mPerformLayout in display content, the window cannot see any insets. Override the
+        // insets state with the global one.
+        final InsetsState insetsState =
+                win.getDisplayContent().getInsetsStateController().getRawInsetsState();
+        win.mAboveInsetsState = insetsState;
+    }
+
     public void setRotation(int rotation, boolean includingWindows) {
         mRotation = rotation;
         updateDisplayFrames();
@@ -272,7 +281,7 @@
     @Test
     public void layoutWindowLw_fitStatusBars() {
         mWindow.mAttrs.setFitInsetsTypes(Type.statusBars());
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -283,7 +292,7 @@
     @Test
     public void layoutWindowLw_fitNavigationBars() {
         mWindow.mAttrs.setFitInsetsTypes(Type.navigationBars());
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -294,7 +303,7 @@
     @Test
     public void layoutWindowLw_fitAllSides() {
         mWindow.mAttrs.setFitInsetsSides(Side.all());
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -305,7 +314,7 @@
     @Test
     public void layoutWindowLw_fitTopOnly() {
         mWindow.mAttrs.setFitInsetsSides(Side.TOP);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -315,11 +324,12 @@
 
     @Test
     public void layoutWindowLw_fitInsetsIgnoringVisibility() {
-        final InsetsState state = mWindow.getInsetsState();
+        final InsetsState state =
+                mDisplayContent.getInsetsStateController().getRawInsetsState();
         state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
         state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
         mWindow.mAttrs.setFitInsetsIgnoringVisibility(true);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -329,11 +339,12 @@
 
     @Test
     public void layoutWindowLw_fitInsetsNotIgnoringVisibility() {
-        final InsetsState state = mWindow.getInsetsState();
+        final InsetsState state =
+                mDisplayContent.getInsetsStateController().getRawInsetsState();
         state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
         state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
         mWindow.mAttrs.setFitInsetsIgnoringVisibility(false);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -349,8 +360,7 @@
         state.getSource(InsetsState.ITYPE_IME).setFrame(
                 0, DISPLAY_HEIGHT - IME_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT);
         mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
-        mWindow.mBehindIme = true;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -364,7 +374,7 @@
 
         mWindow.mAttrs.setFitInsetsTypes(Type.displayCutout());
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -379,7 +389,7 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -395,7 +405,7 @@
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -411,7 +421,7 @@
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -427,7 +437,7 @@
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -442,7 +452,7 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -457,11 +467,12 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
-        mWindow.getInsetsState().getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
+        mDisplayContent.getInsetsStateController().getRawInsetsState()
+                .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
         final InsetsState requestedState = new InsetsState();
         requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
         mWindow.updateRequestedVisibility(requestedState);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -476,12 +487,13 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
-        mWindow.getInsetsState().getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
+        mDisplayContent.getInsetsStateController().getRawInsetsState()
+                .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
         final InsetsState requestedState = new InsetsState();
         requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
         mWindow.updateRequestedVisibility(requestedState);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -497,7 +509,7 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -513,7 +525,7 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -529,7 +541,7 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -545,7 +557,7 @@
         mWindow.mAttrs.type = TYPE_APPLICATION_OVERLAY;
         mWindow.mAttrs.width = DISPLAY_WIDTH;
         mWindow.mAttrs.height = DISPLAY_HEIGHT;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -562,7 +574,7 @@
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -576,7 +588,7 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -592,7 +604,7 @@
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -608,7 +620,7 @@
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -624,7 +636,7 @@
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
@@ -638,7 +650,7 @@
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING;
-        addWindow(mWindow);
+        addWindowWithRawInsetsState(mWindow);
 
         final int forwardedInsetBottom = 50;
         mDisplayPolicy.setForwardedInsets(Insets.of(0, 0, 0, forwardedInsetBottom));
@@ -776,9 +788,13 @@
     public void testFixedRotationInsetsSourceFrame() {
         doReturn((mDisplayContent.getRotation() + 1) % 4).when(mDisplayContent)
                 .rotationForActivityInDifferentOrientation(eq(mWindow.mActivityRecord));
-        final Rect frame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+        mWindow.mAboveInsetsState.addSource(mDisplayContent.getInsetsStateController()
+                .getRawInsetsState().peekSource(ITYPE_STATUS_BAR));
+        final Rect frame = mDisplayPolicy.getInsetsPolicy().getInsetsForWindow(mWindow)
+                .getSource(ITYPE_STATUS_BAR).getFrame();
         mDisplayContent.rotateInDifferentOrientationIfNeeded(mWindow.mActivityRecord);
-        final Rect rotatedFrame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+        final Rect rotatedFrame = mDisplayPolicy.getInsetsPolicy().getInsetsForWindow(mWindow)
+                .getSource(ITYPE_STATUS_BAR).getFrame();
 
         assertEquals(DISPLAY_WIDTH, frame.width());
         assertEquals(DISPLAY_HEIGHT, rotatedFrame.width());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 77537a9..499507e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -300,6 +300,7 @@
         displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
         mNavBarWindow.getControllableInsetProvider().setServerVisible(true);
         final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
+        mImeWindow.mAboveInsetsState = state;
         mDisplayContent.mDisplayFrames = new DisplayFrames(mDisplayContent.getDisplayId(),
                 state, displayInfo, null /* displayCutout */);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index e0fd379..bf3ed69 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -45,6 +45,7 @@
 
 import android.app.StatusBarManager;
 import android.platform.test.annotations.Presubmit;
+import android.view.InsetsSource;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 
@@ -272,7 +273,6 @@
         final WindowState navBar = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar");
         navBar.setHasSurface(true);
         navBar.getControllableInsetProvider().setServerVisible(true);
-
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
         doNothing().when(policy).startAnimation(anyBoolean(), any());
 
@@ -337,11 +337,14 @@
     @UseTestDisplay(addWindows = W_ACTIVITY)
     @Test
     public void testAbortTransientBars_bothCanBeAborted_appGetsBothRealControls() {
-        addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
-                .getControllableInsetProvider().getSource().setVisible(false);
-        addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
-                .getControllableInsetProvider().getSource().setVisible(false);
-
+        final InsetsSource statusBarSource = addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
+                .getControllableInsetProvider().getSource();
+        final InsetsSource navBarSource = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
+                .getControllableInsetProvider().getSource();
+        statusBarSource.setVisible(false);
+        navBarSource.setVisible(false);
+        mAppWindow.mAboveInsetsState.addSource(navBarSource);
+        mAppWindow.mAboveInsetsState.addSource(statusBarSource);
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
         doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(mAppWindow);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 2766438..2107ab1e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -59,25 +59,6 @@
 public class InsetsStateControllerTest extends WindowTestsBase {
 
     @Test
-    public void testStripForDispatch_notOwn() {
-        final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
-        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
-        statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR));
-        assertNotNull(getController().getInsetsForWindow(app).peekSource(ITYPE_STATUS_BAR));
-    }
-
-    @Test
-    public void testStripForDispatch_own() {
-        final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
-        mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
-                .setWindow(statusBar, null, null);
-        statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR));
-        final InsetsState state = getController().getInsetsForWindow(statusBar);
-        assertNull(state.peekSource(ITYPE_STATUS_BAR));
-    }
-
-    @Test
     public void testStripForDispatch_navBar() {
         final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
         final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
@@ -142,14 +123,15 @@
         getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
 
         final WindowState app1 = createWindow(null, TYPE_APPLICATION, "app1");
-        app1.mBehindIme = true;
-
         final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
-        app2.mBehindIme = false;
+
+        app1.mAboveInsetsState.addSource(getController().getRawInsetsState().getSource(ITYPE_IME));
 
         getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
-        assertFalse(getController().getInsetsForWindow(app2).getSource(ITYPE_IME).isVisible());
-        assertTrue(getController().getInsetsForWindow(app1).getSource(ITYPE_IME).isVisible());
+        assertFalse(getController().getInsetsForWindow(app2).getSource(ITYPE_IME)
+                .isVisible());
+        assertTrue(getController().getInsetsForWindow(app1).getSource(ITYPE_IME)
+                .isVisible());
     }
 
     @UseTestDisplay(addWindows = W_INPUT_METHOD)
@@ -158,7 +140,8 @@
         getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
 
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        app.mBehindIme = true;
+        app.mAboveInsetsState.getSource(ITYPE_IME).setVisible(true);
+        app.mAboveInsetsState.getSource(ITYPE_IME).setFrame(mImeWindow.getFrame());
 
         getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
         assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
@@ -170,10 +153,10 @@
         getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
 
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        app.mBehindIme = false;
 
         getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
-        assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
+        assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME)
+                .isVisible());
     }
 
     @UseTestDisplay(addWindows = W_INPUT_METHOD)
@@ -210,7 +193,8 @@
 
         // app won't get visible IME insets while above IME even when IME is visible.
         assertTrue(getController().getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
-        assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
+        assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME)
+                .isVisible());
 
         // Reset invocation counter.
         clearInvocations(app);
@@ -219,6 +203,8 @@
         app.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
         mDisplayContent.computeImeTarget(true);
         mDisplayContent.applySurfaceChangesTransaction();
+        app.mAboveInsetsState.getSource(ITYPE_IME).setVisible(true);
+        app.mAboveInsetsState.getSource(ITYPE_IME).setFrame(mImeWindow.getFrame());
 
         // Make sure app got notified.
         verify(app, atLeast(1)).notifyInsetsChanged();
@@ -234,6 +220,8 @@
 
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
+        app.mAboveInsetsState.set(getController().getRawInsetsState());
+        child.mAboveInsetsState.set(getController().getRawInsetsState());
         child.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
 
         mDisplayContent.computeImeTarget(true);
@@ -242,7 +230,8 @@
 
         getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
         assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
-        assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME).isVisible());
+        assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME)
+                .isVisible());
     }
 
     @UseTestDisplay(addWindows = W_INPUT_METHOD)
@@ -252,6 +241,7 @@
 
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
+        app.mAboveInsetsState.addSource(getController().getRawInsetsState().peekSource(ITYPE_IME));
         child.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
         child.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
 
@@ -261,7 +251,8 @@
 
         getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
         assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
-        assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME).isVisible());
+        assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME)
+                .isVisible());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 1607f01..a1f89ec 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -275,7 +275,7 @@
         imeSource.setFrame(imeFrame);
         imeSource.setVisible(true);
         w.updateRequestedVisibility(state);
-        w.mBehindIme = true;
+        w.mAboveInsetsState.addSource(imeSource);
 
         // With no insets or system decor all the frames incoming from PhoneWindowManager
         // are identical.
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 3815326..0cb1255 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -79,7 +79,6 @@
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -111,6 +110,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
 
 /**
  * A service that collects, aggregates, and persists application usage data.
@@ -162,7 +162,7 @@
     ShortcutServiceInternal mShortcutServiceInternal;
 
     private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
-    private final SparseBooleanArray mUserUnlockedStates = new SparseBooleanArray();
+    private final CopyOnWriteArraySet<Integer> mUserUnlockedStates = new CopyOnWriteArraySet<>();
     private final SparseIntArray mUidToKernelCounter = new SparseIntArray();
     int mUsageSource;
 
@@ -333,7 +333,7 @@
 
         synchronized (mLock) {
             // User was started but never unlocked so no need to report a user stopped event
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 persistPendingEventsLocked(userId);
                 return;
             }
@@ -346,7 +346,7 @@
             if (userService != null) {
                 userService.userStopped();
             }
-            mUserUnlockedStates.put(userId, false);
+            mUserUnlockedStates.remove(userId);
             mUserState.put(userId, null); // release the service (mainly for GC)
         }
     }
@@ -360,6 +360,11 @@
             UsageStatsIdleService.scheduleUpdateMappingsJob(getContext());
         }
         synchronized (mLock) {
+            // This should be safe to add this early. Other than reportEventOrAddToQueue, every
+            // other user grabs the lock before accessing
+            // mUserUnlockedStates. reportEventOrAddToQueue does not depend on anything other than
+            // mUserUnlockedStates, and the lock will protect the handler.
+            mUserUnlockedStates.add(userId);
             // Create a user unlocked event to report
             final Event unlockEvent = new Event(USER_UNLOCKED, SystemClock.elapsedRealtime());
             unlockEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
@@ -377,7 +382,6 @@
 
             initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(),
                     installedPackages);
-            mUserUnlockedStates.put(userId, true);
             final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId);
             if (userService == null) {
                 Slog.i(TAG, "Attempted to unlock stopped or removed user " + userId);
@@ -780,12 +784,11 @@
     }
 
     private void reportEventOrAddToQueue(int userId, Event event) {
+        if (mUserUnlockedStates.contains(userId)) {
+            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
+            return;
+        }
         synchronized (mLock) {
-            if (mUserUnlockedStates.get(userId)) {
-                mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
-                return;
-            }
-
             LinkedList<Event> events = mReportedEvents.get(userId);
             if (events == null) {
                 events = new LinkedList<>();
@@ -823,7 +826,7 @@
 
         synchronized (mLock) {
             // This should never be called directly when the user is locked
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 Slog.wtf(TAG, "Failed to report event for locked user " + userId
                         + " (" + event.mPackage + "/" + event.mClass
                         + " eventType:" + event.mEventType
@@ -1006,7 +1009,7 @@
         final int tokenRemoved;
         synchronized (mLock) {
             final long timeRemoved = System.currentTimeMillis();
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 // If user is not unlocked and a package is removed for them, we will handle it
                 // when the user service is initialized and package manager is queried.
                 return;
@@ -1030,7 +1033,7 @@
      */
     private boolean pruneUninstalledPackagesData(int userId) {
         synchronized (mLock) {
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 return false; // user is no longer unlocked
             }
 
@@ -1050,7 +1053,7 @@
         // fetch the installed packages outside the lock so it doesn't block package manager.
         final HashMap<String, Long> installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM);
         synchronized (mLock) {
-            if (!mUserUnlockedStates.get(UserHandle.USER_SYSTEM)) {
+            if (!mUserUnlockedStates.contains(UserHandle.USER_SYSTEM)) {
                 return false; // user is no longer unlocked
             }
 
@@ -1069,7 +1072,7 @@
     List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
             boolean obfuscateInstantApps) {
         synchronized (mLock) {
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 Slog.w(TAG, "Failed to query usage stats for locked user " + userId);
                 return null;
             }
@@ -1103,7 +1106,7 @@
     List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
             long endTime) {
         synchronized (mLock) {
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 Slog.w(TAG, "Failed to query configuration stats for locked user " + userId);
                 return null;
             }
@@ -1122,7 +1125,7 @@
     List<EventStats> queryEventStats(int userId, int bucketType, long beginTime,
             long endTime) {
         synchronized (mLock) {
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 Slog.w(TAG, "Failed to query event stats for locked user " + userId);
                 return null;
             }
@@ -1140,7 +1143,7 @@
      */
     UsageEvents queryEvents(int userId, long beginTime, long endTime, int flags) {
         synchronized (mLock) {
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 Slog.w(TAG, "Failed to query events for locked user " + userId);
                 return null;
             }
@@ -1159,7 +1162,7 @@
     UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime,
             String packageName, boolean includeTaskRoot) {
         synchronized (mLock) {
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 Slog.w(TAG, "Failed to query package events for locked user " + userId);
                 return null;
             }
@@ -1203,7 +1206,7 @@
         final int userCount = mUserState.size();
         for (int i = 0; i < userCount; i++) {
             final int userId = mUserState.keyAt(i);
-            if (!mUserUnlockedStates.get(userId)) {
+            if (!mUserUnlockedStates.contains(userId)) {
                 persistPendingEventsLocked(userId);
                 continue;
             }
@@ -1261,7 +1264,7 @@
                             final int numUsers = mUserState.size();
                             for (int user = 0; user < numUsers; user++) {
                                 final int userId = mUserState.keyAt(user);
-                                if (!mUserUnlockedStates.get(userId)) {
+                                if (!mUserUnlockedStates.contains(userId)) {
                                     continue;
                                 }
                                 ipw.println("user=" + userId);
@@ -1288,7 +1291,7 @@
                             final int numUsers = mUserState.size();
                             for (int user = 0; user < numUsers; user++) {
                                 final int userId = mUserState.keyAt(user);
-                                if (!mUserUnlockedStates.get(userId)) {
+                                if (!mUserUnlockedStates.contains(userId)) {
                                     continue;
                                 }
                                 ipw.println("user=" + userId);
@@ -1344,7 +1347,7 @@
                 idpw.printPair("user", userId);
                 idpw.println();
                 idpw.increaseIndent();
-                if (mUserUnlockedStates.get(userId)) {
+                if (mUserUnlockedStates.contains(userId)) {
                     if (checkin) {
                         mUserState.valueAt(i).checkin(idpw);
                     } else {
@@ -1382,7 +1385,7 @@
             ipw.println("the specified user does not exist.");
             return UserHandle.USER_NULL;
         }
-        if (!mUserUnlockedStates.get(userId)) {
+        if (!mUserUnlockedStates.contains(userId)) {
             ipw.println("the specified user is currently in a locked state.");
             return UserHandle.USER_NULL;
         }
@@ -2250,12 +2253,11 @@
 
         @Override
         public byte[] getBackupPayload(int user, String key) {
+            if (!mUserUnlockedStates.contains(user)) {
+                Slog.w(TAG, "Failed to get backup payload for locked user " + user);
+                return null;
+            }
             synchronized (mLock) {
-                if (!mUserUnlockedStates.get(user)) {
-                    Slog.w(TAG, "Failed to get backup payload for locked user " + user);
-                    return null;
-                }
-
                 // Check to ensure that only user 0's data is b/r for now
                 // Note: if backup and restore is enabled for users other than the system user, the
                 // #onUserUnlocked logic, specifically when the update mappings job is scheduled via
@@ -2275,7 +2277,7 @@
         @Override
         public void applyRestoredPayload(int user, String key, byte[] payload) {
             synchronized (mLock) {
-                if (!mUserUnlockedStates.get(user)) {
+                if (!mUserUnlockedStates.contains(user)) {
                     Slog.w(TAG, "Failed to apply restored payload for locked user " + user);
                     return;
                 }
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 1faae42..a9dae89 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -138,6 +138,8 @@
      * Indicates if the session is for a conference call or not. If not defined, should be
      * considered {@code false}.
      * Boolean extra properties - {@code true} / {@code false}.
+     *
+     * This extra is set on an instance of {@link ImsCallProfile} via {@link #setCallExtraBoolean}.
      * @hide
      */
     @SystemApi
@@ -174,6 +176,8 @@
      * Indicates if the session can be extended to a conference call. If not defined, should be
      * considered {@code false}.
      * Boolean extra properties - {@code true} / {@code false}.
+     *
+     * This extra is set on an instance of {@link ImsCallProfile} via {@link #setCallExtraBoolean}.
      * @hide
      */
     @SystemApi
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 22aa18f..d17415a 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2360,6 +2360,16 @@
      */
     String getContactFromEab(String contact);
 
+    /*
+     * Check whether the device supports RCS User Capability Exchange or not.
+     */
+    boolean getDeviceUceEnabled();
+
+    /*
+     * Set the device supports RCS User Capability Exchange.
+     */
+     void setDeviceUceEnabled(boolean isEnabled);
+
     /**
      * Set a SignalStrengthUpdateRequest to receive notification when Signal Strength breach the
      * specified thresholds.
diff --git a/tests/FlickerTests/TEST_MAPPING b/tests/FlickerTests/TEST_MAPPING
deleted file mode 100644
index db251b9..0000000
--- a/tests/FlickerTests/TEST_MAPPING
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "postsubmit": [
-    // Run tests on real device
-    {
-      "name": "FlickerTests",
-      "keywords": ["primary-device"]
-    },
-    // Also run the tests in the cloud
-    {
-      "name": "FlickerTests"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 104758d..5381009 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -98,6 +98,8 @@
     private final TestClock mTestClock = new TestClock();
     private TestLooper mTestLooper;
     private Context mSpyContext;
+    // Keep track of all created watchdogs to apply device config changes
+    private List<PackageWatchdog> mAllocatedWatchdogs;
     @Mock
     private ConnectivityModuleConnector mConnectivityModuleConnector;
     @Mock
@@ -112,7 +114,8 @@
         MockitoAnnotations.initMocks(this);
         new File(InstrumentationRegistry.getContext().getFilesDir(),
                 "package-watchdog.xml").delete();
-        adoptShellPermissions(Manifest.permission.READ_DEVICE_CONFIG);
+        adoptShellPermissions(Manifest.permission.READ_DEVICE_CONFIG,
+                Manifest.permission.WRITE_DEVICE_CONFIG);
         mTestLooper = new TestLooper();
         mSpyContext = spy(InstrumentationRegistry.getContext());
         when(mSpyContext.getPackageManager()).thenReturn(mMockPackageManager);
@@ -157,12 +160,23 @@
                     return storedValue == null ? defaultValue : Long.parseLong(storedValue);
                 }
         ).when(() -> SystemProperties.getLong(anyString(), anyLong()));
+
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+                PackageWatchdog.PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED,
+                Boolean.toString(true), false);
+
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+                PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
+                Integer.toString(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT), false);
+
+        mAllocatedWatchdogs = new ArrayList<>();
     }
 
     @After
     public void tearDown() throws Exception {
         dropShellPermissions();
         mSession.finishMocking();
+        mAllocatedWatchdogs.clear();
     }
 
     @Test
@@ -611,10 +625,6 @@
      */
     @Test
     public void testExplicitHealthCheckStateChanges() throws Exception {
-        adoptShellPermissions(
-                Manifest.permission.WRITE_DEVICE_CONFIG,
-                Manifest.permission.READ_DEVICE_CONFIG);
-
         TestController controller = new TestController();
         PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */);
         TestObserver observer = new TestObserver(OBSERVER_NAME_1,
@@ -807,9 +817,6 @@
     /** Test default values are used when device property is invalid. */
     @Test
     public void testInvalidConfig_watchdogTriggerFailureCount() {
-        adoptShellPermissions(
-                Manifest.permission.WRITE_DEVICE_CONFIG,
-                Manifest.permission.READ_DEVICE_CONFIG);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                 PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
                 Integer.toString(-1), /*makeDefault*/false);
@@ -835,9 +842,6 @@
     /** Test default values are used when device property is invalid. */
     @Test
     public void testInvalidConfig_watchdogTriggerDurationMillis() {
-        adoptShellPermissions(
-                Manifest.permission.WRITE_DEVICE_CONFIG,
-                Manifest.permission.READ_DEVICE_CONFIG);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                 PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
                 Integer.toString(2), /*makeDefault*/false);
@@ -850,7 +854,6 @@
         watchdog.startObservingHealth(observer, Arrays.asList(APP_A, APP_B), Long.MAX_VALUE);
         watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
-        mTestLooper.dispatchAll();
         moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS + 1);
         watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
@@ -862,7 +865,6 @@
 
         watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
-        mTestLooper.dispatchAll();
         moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS - 1);
         watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
@@ -917,9 +919,6 @@
     /** Test we are notified when enough failures are triggered within any window. */
     @Test
     public void testFailureTriggerWindow() {
-        adoptShellPermissions(
-                Manifest.permission.WRITE_DEVICE_CONFIG,
-                Manifest.permission.READ_DEVICE_CONFIG);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                 PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
                 Integer.toString(3), /*makeDefault*/false);
@@ -933,11 +932,9 @@
         // Raise 2 failures at t=0 and t=900 respectively
         watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
-        mTestLooper.dispatchAll();
         moveTimeForwardAndDispatch(900);
         watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
-        mTestLooper.dispatchAll();
 
         // Raise 2 failures at t=1100
         moveTimeForwardAndDispatch(200);
@@ -1303,15 +1300,15 @@
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
                 PackageWatchdog.PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED,
                 Boolean.toString(enabled), /*makeDefault*/false);
-        //give time for DeviceConfig to broadcast the property value change
-        try {
-            Thread.sleep(SHORT_DURATION);
-        } catch (InterruptedException e) {
-            fail("Thread.sleep unexpectedly failed!");
+        // Call updateConfigs() so device config changes take effect immediately
+        for (PackageWatchdog watchdog : mAllocatedWatchdogs) {
+            watchdog.updateConfigs();
         }
     }
 
     private void moveTimeForwardAndDispatch(long milliSeconds) {
+        // Exhaust all due runnables now which shouldn't be executed after time-leap
+        mTestLooper.dispatchAll();
         mTestClock.moveTimeForward(milliSeconds);
         mTestLooper.moveTimeForward(milliSeconds);
         mTestLooper.dispatchAll();
@@ -1354,6 +1351,7 @@
             verify(mConnectivityModuleConnector).registerHealthListener(
                     mConnectivityModuleCallbackCaptor.capture());
         }
+        mAllocatedWatchdogs.add(watchdog);
         return watchdog;
     }
 
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 0db2b2a..7b2a07f 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -1225,4 +1225,44 @@
             InstallUtils.dropShellPermissionIdentity();
         }
     }
+
+    /**
+     * Tests an app can be rolled back to the previous signing key.
+     *
+     * <p>The rollback capability in the signing lineage allows an app to be updated to an APK
+     * signed with a previous signing key in the lineage; however this often defeats the purpose
+     * of key rotation as a compromised key could then be used to roll an app back to the previous
+     * key. To avoid requiring the rollback capability to support app rollbacks the PackageManager
+     * allows an app to be rolled back to the previous signing key if the rollback install reason
+     * is set.
+     */
+    @Test
+    public void testRollbackAfterKeyRotation() throws Exception {
+        try {
+            InstallUtils.adoptShellPermissionIdentity(
+                    Manifest.permission.INSTALL_PACKAGES,
+                    Manifest.permission.DELETE_PACKAGES,
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
+                    Manifest.permission.MANAGE_ROLLBACKS);
+
+            // Uninstall TestApp.A
+            Uninstall.packages(TestApp.A);
+            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
+
+            // Install v1 of the app with the original signing key (without rollbacks enabled).
+            Install.single(TestApp.AOriginal1).commit();
+            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+
+            // Upgrade from v1 to v2 with the rotated signing key, with rollbacks enabled.
+            Install.single(TestApp.ARotated2).setEnableRollback().commit();
+            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+
+            // Roll back the app.
+            RollbackInfo available = waitForAvailableRollback(TestApp.A);
+            RollbackUtils.rollback(available.getRollbackId());
+            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+        } finally {
+            InstallUtils.dropShellPermissionIdentity();
+        }
+    }
 }
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
index ef973ac..861d221 100644
--- a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
+++ b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
@@ -182,6 +182,24 @@
 
     @SmallTest
     @Test
+    public void setFunctionsNcmAndRndis() {
+        final long rndisPlusNcm = UsbManager.FUNCTION_RNDIS | UsbManager.FUNCTION_NCM;
+
+        mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+                UsbManager.FUNCTION_NCM));
+        assertEquals(UsbManager.FUNCTION_NCM, mUsbHandler.getEnabledFunctions() & rndisPlusNcm);
+
+        mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+                rndisPlusNcm));
+        assertEquals(rndisPlusNcm, mUsbHandler.getEnabledFunctions() & rndisPlusNcm);
+
+        mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+                UsbManager.FUNCTION_NCM));
+        assertEquals(UsbManager.FUNCTION_NCM, mUsbHandler.getEnabledFunctions() & rndisPlusNcm);
+    }
+
+    @SmallTest
+    @Test
     public void enableAdb() {
         sendBootCompleteMessages(mUsbHandler);
         Message msg = mUsbHandler.obtainMessage(MSG_ENABLE_ADB);