Merge "Cache OTP callback if the device is still under address allocation"
diff --git a/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java
index a807eb1..5b14056 100644
--- a/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java
@@ -36,7 +36,7 @@
         SystemServiceRegistry.registerCachedService(
                 Context.DEVICE_IDLE_CONTROLLER, DeviceIdleManager.class,
                 (context, b) -> new DeviceIdleManager(
-                        context.getOuterContext(), IDeviceIdleController.Stub.asInterface(b)));
+                        context, IDeviceIdleController.Stub.asInterface(b)));
         PowerManager.setIsIgnoringBatteryOptimizationsCallback((packageName) -> {
             // No need for synchronization on sIDeviceIdleController; worst case
             // we just initialize it twice.
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
new file mode 100644
index 0000000..3cfb080
--- /dev/null
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -0,0 +1,112 @@
+package com.android.server.usage;
+
+import android.app.usage.AppStandbyInfo;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManager.StandbyBuckets;
+import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
+import android.content.Context;
+import android.os.Looper;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.Set;
+
+public interface AppStandbyInternal {
+    /**
+     * TODO AppStandbyController should probably be a binder service, and then we shouldn't need
+     * this method.
+     */
+    static AppStandbyInternal newAppStandbyController(ClassLoader loader, Context context,
+            Looper looper) {
+        try {
+            final Class<?> clazz = Class.forName("com.android.server.usage.AppStandbyController",
+                    true, loader);
+            final Constructor<?> ctor =  clazz.getConstructor(Context.class, Looper.class);
+            return (AppStandbyInternal) ctor.newInstance(context, looper);
+        } catch (NoSuchMethodException | InstantiationException
+                | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) {
+            throw new RuntimeException("Unable to instantiate AppStandbyController!", e);
+        }
+    }
+
+    void onBootPhase(int phase);
+
+    boolean isParoledOrCharging();
+
+    void postCheckIdleStates(int userId);
+
+    /**
+     * We send a different message to check idle states once, otherwise we would end up
+     * scheduling a series of repeating checkIdleStates each time we fired off one.
+     */
+    void postOneTimeCheckIdleStates();
+
+    void reportEvent(UsageEvents.Event event, long elapsedRealtime, int userId);
+
+    void setLastJobRunTime(String packageName, int userId, long elapsedRealtime);
+
+    long getTimeSinceLastJobRun(String packageName, int userId);
+
+    void onUserRemoved(int userId);
+
+    void addListener(AppIdleStateChangeListener listener);
+
+    void removeListener(AppIdleStateChangeListener listener);
+
+    int getAppId(String packageName);
+
+    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+            boolean shouldObfuscateInstantApps);
+
+    /**
+     * Checks if an app has been idle for a while and filters out apps that are excluded.
+     * It returns false if the current system state allows all apps to be considered active.
+     * This happens if the device is plugged in or temporarily allowed to make exceptions.
+     * Called by interface impls.
+     */
+    boolean isAppIdleFiltered(String packageName, int appId, int userId,
+            long elapsedRealtime);
+
+    int[] getIdleUidsForUser(int userId);
+
+    void setAppIdleAsync(String packageName, boolean idle, int userId);
+
+    @StandbyBuckets
+    int getAppStandbyBucket(String packageName, int userId,
+            long elapsedRealtime, boolean shouldObfuscateInstantApps);
+
+    List<AppStandbyInfo> getAppStandbyBuckets(int userId);
+
+    void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
+            int reason, long elapsedRealtime, boolean resetTimeout);
+
+    void addActiveDeviceAdmin(String adminPkg, int userId);
+
+    void setActiveAdminApps(Set<String> adminPkgs, int userId);
+
+    void onAdminDataAvailable();
+
+    void clearCarrierPrivilegedApps();
+
+    void flushToDisk(int userId);
+
+    void flushDurationsToDisk();
+
+    void initializeDefaultsForSystemApps(int userId);
+
+    void postReportContentProviderUsage(String name, String packageName, int userId);
+
+    void postReportSyncScheduled(String packageName, int userId, boolean exempted);
+
+    void postReportExemptedSyncStart(String packageName, int userId);
+
+    void dumpUser(IndentingPrintWriter idpw, int userId, String pkg);
+
+    void dumpState(String[] args, PrintWriter pw);
+
+    boolean isAppIdleEnabled();
+}
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
similarity index 100%
rename from services/usage/java/com/android/server/usage/AppIdleHistory.java
rename to apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
similarity index 95%
rename from services/usage/java/com/android/server/usage/AppStandbyController.java
rename to apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 75e8fb5..df5d6ae 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -120,9 +120,9 @@
  * Manages the standby state of an app, listening to various events.
  *
  * Unit test:
-   atest ${ANDROID_BUILD_TOP}/frameworks/base/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+   atest com.android.server.usage.AppStandbyControllerTests
  */
-public class AppStandbyController {
+public class AppStandbyController implements AppStandbyInternal {
 
     private static final String TAG = "AppStandbyController";
     static final boolean DEBUG = false;
@@ -247,7 +247,7 @@
     /** The length of time phone must be charging before considered stable enough to run jobs  */
     long mStableChargingThresholdMillis;
 
-    volatile boolean mAppIdleEnabled;
+    private volatile boolean mAppIdleEnabled;
     boolean mAppIdleTempParoled;
     boolean mCharging;
     boolean mChargingStable;
@@ -320,7 +320,7 @@
         }
     }
 
-    AppStandbyController(Context context, Looper looper) {
+    public AppStandbyController(Context context, Looper looper) {
         this(new Injector(context, looper));
     }
 
@@ -351,6 +351,7 @@
                 null, mHandler);
     }
 
+    @VisibleForTesting
     void setAppIdleEnabled(boolean enabled) {
         synchronized (mAppIdleLock) {
             if (mAppIdleEnabled != enabled) {
@@ -363,6 +364,12 @@
         }
     }
 
+    @Override
+    public boolean isAppIdleEnabled() {
+        return mAppIdleEnabled;
+    }
+
+    @Override
     public void onBootPhase(int phase) {
         mInjector.onBootPhase(phase);
         if (phase == PHASE_SYSTEM_SERVICES_READY) {
@@ -400,7 +407,7 @@
         }
     }
 
-    void reportContentProviderUsage(String authority, String providerPkgName, int userId) {
+    private void reportContentProviderUsage(String authority, String providerPkgName, int userId) {
         if (!mAppIdleEnabled) return;
 
         // Get sync adapters for the authority
@@ -432,7 +439,7 @@
         }
     }
 
-    void reportExemptedSyncScheduled(String packageName, int userId) {
+    private void reportExemptedSyncScheduled(String packageName, int userId) {
         if (!mAppIdleEnabled) return;
 
         final int bucketToPromote;
@@ -463,7 +470,7 @@
         }
     }
 
-    void reportUnexemptedSyncScheduled(String packageName, int userId) {
+    private void reportUnexemptedSyncScheduled(String packageName, int userId) {
         if (!mAppIdleEnabled) return;
 
         final long elapsedRealtime = mInjector.elapsedRealtime();
@@ -482,7 +489,7 @@
         }
     }
 
-    void reportExemptedSyncStart(String packageName, int userId) {
+    private void reportExemptedSyncStart(String packageName, int userId) {
         if (!mAppIdleEnabled) return;
 
         final long elapsedRealtime = mInjector.elapsedRealtime();
@@ -497,6 +504,7 @@
         }
     }
 
+    @VisibleForTesting
     void setChargingState(boolean charging) {
         synchronized (mAppIdleLock) {
             if (mCharging != charging) {
@@ -517,7 +525,7 @@
         }
     }
 
-    void updateChargingStableState() {
+    private void updateChargingStableState() {
         synchronized (mAppIdleLock) {
             if (mChargingStable != mCharging) {
                 if (DEBUG) Slog.d(TAG, "Setting mChargingStable to " + mCharging);
@@ -527,8 +535,7 @@
         }
     }
 
-    /** Paroled here means temporary pardon from being inactive */
-    void setAppIdleParoled(boolean paroled) {
+    private void setAppIdleParoled(boolean paroled) {
         synchronized (mAppIdleLock) {
             final long now = mInjector.currentTimeMillis();
             if (mAppIdleTempParoled != paroled) {
@@ -545,7 +552,8 @@
         }
     }
 
-    boolean isParoledOrCharging() {
+    @Override
+    public boolean isParoledOrCharging() {
         if (!mAppIdleEnabled) return true;
         synchronized (mAppIdleLock) {
             // Only consider stable charging when determining charge state.
@@ -583,15 +591,13 @@
         mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED);
     }
 
-    void postCheckIdleStates(int userId) {
+    @Override
+    public void postCheckIdleStates(int userId) {
         mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
     }
 
-    /**
-     * We send a different message to check idle states once, otherwise we would end up
-     * scheduling a series of repeating checkIdleStates each time we fired off one.
-     */
-    void postOneTimeCheckIdleStates() {
+    @Override
+    public void postOneTimeCheckIdleStates() {
         if (mInjector.getBootPhase() < PHASE_SYSTEM_SERVICES_READY) {
             // Not booted yet; wait for it!
             mPendingOneTimeCheckIdleStates = true;
@@ -601,10 +607,7 @@
         }
     }
 
-    /**
-     * Check all running users' or specified user's apps to see if they enter an idle state.
-     * @return Returns whether checking should continue periodically.
-     */
+    @VisibleForTesting
     boolean checkIdleStates(int checkUserId) {
         if (!mAppIdleEnabled) {
             return false;
@@ -776,19 +779,15 @@
      * @return the bucket for the app, based on time since last used
      */
     @GuardedBy("mAppIdleLock")
-    @StandbyBuckets int getBucketForLocked(String packageName, int userId,
+    @StandbyBuckets
+    private int getBucketForLocked(String packageName, int userId,
             long elapsedRealtime) {
         int bucketIndex = mAppIdleHistory.getThresholdIndex(packageName, userId,
                 elapsedRealtime, mAppStandbyScreenThresholds, mAppStandbyElapsedThresholds);
         return THRESHOLD_BUCKETS[bucketIndex];
     }
 
-    /**
-     * Check if it's been a while since last parole and let idle apps do some work.
-     * If network is not available, delay parole until it is available up until the end of the
-     * parole window. Force the parole to be set if end of the parole window is reached.
-     */
-    void checkParoleTimeout() {
+    private void checkParoleTimeout() {
         boolean setParoled = false;
         boolean waitForNetwork = false;
         NetworkInfo activeNetwork = mConnectivityManager.getActiveNetworkInfo();
@@ -845,7 +844,7 @@
         }
     }
 
-    void onDeviceIdleModeChanged() {
+    private void onDeviceIdleModeChanged() {
         final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
         if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
         boolean paroled = false;
@@ -869,7 +868,8 @@
         setAppIdleParoled(paroled);
     }
 
-    void reportEvent(UsageEvents.Event event, long elapsedRealtime, int userId) {
+    @Override
+    public void reportEvent(UsageEvents.Event event, long elapsedRealtime, int userId) {
         if (!mAppIdleEnabled) return;
         synchronized (mAppIdleLock) {
             // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
@@ -950,14 +950,7 @@
         }
     }
 
-    /**
-     * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle,
-     * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind
-     * the threshold for idle.
-     *
-     * This method is always called from the handler thread, so not much synchronization is
-     * required.
-     */
+    @VisibleForTesting
     void forceIdleState(String packageName, int userId, boolean idle) {
         if (!mAppIdleEnabled) return;
 
@@ -983,12 +976,14 @@
         }
     }
 
+    @Override
     public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.setLastJobRunTime(packageName, userId, elapsedRealtime);
         }
     }
 
+    @Override
     public long getTimeSinceLastJobRun(String packageName, int userId) {
         final long elapsedRealtime = mInjector.elapsedRealtime();
         synchronized (mAppIdleLock) {
@@ -996,6 +991,7 @@
         }
     }
 
+    @Override
     public void onUserRemoved(int userId) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.onUserRemoved(userId);
@@ -1011,7 +1007,8 @@
         }
     }
 
-    void addListener(AppIdleStateChangeListener listener) {
+    @Override
+    public void addListener(AppIdleStateChangeListener listener) {
         synchronized (mPackageAccessListeners) {
             if (!mPackageAccessListeners.contains(listener)) {
                 mPackageAccessListeners.add(listener);
@@ -1019,13 +1016,15 @@
         }
     }
 
-    void removeListener(AppIdleStateChangeListener listener) {
+    @Override
+    public void removeListener(AppIdleStateChangeListener listener) {
         synchronized (mPackageAccessListeners) {
             mPackageAccessListeners.remove(listener);
         }
     }
 
-    int getAppId(String packageName) {
+    @Override
+    public int getAppId(String packageName) {
         try {
             ApplicationInfo ai = mPackageManager.getApplicationInfo(packageName,
                     PackageManager.MATCH_ANY_USER
@@ -1036,7 +1035,8 @@
         }
     }
 
-    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+    @Override
+    public boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
             boolean shouldObfuscateInstantApps) {
         if (isParoledOrCharging()) {
             return false;
@@ -1048,8 +1048,7 @@
         return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
     }
 
-    /** Returns true if this app should be whitelisted for some reason, to never go into standby */
-    boolean isAppSpecial(String packageName, int appId, int userId) {
+    private boolean isAppSpecial(String packageName, int appId, int userId) {
         if (packageName == null) return false;
         // If not enabled at all, of course nobody is ever idle.
         if (!mAppIdleEnabled) {
@@ -1102,13 +1101,8 @@
         return false;
     }
 
-    /**
-     * Checks if an app has been idle for a while and filters out apps that are excluded.
-     * It returns false if the current system state allows all apps to be considered active.
-     * This happens if the device is plugged in or temporarily allowed to make exceptions.
-     * Called by interface impls.
-     */
-    boolean isAppIdleFiltered(String packageName, int appId, int userId,
+    @Override
+    public boolean isAppIdleFiltered(String packageName, int appId, int userId,
             long elapsedRealtime) {
         if (isAppSpecial(packageName, appId, userId)) {
             return false;
@@ -1117,7 +1111,8 @@
         }
     }
 
-    int[] getIdleUidsForUser(int userId) {
+    @Override
+    public int[] getIdleUidsForUser(int userId) {
         if (!mAppIdleEnabled) {
             return new int[0];
         }
@@ -1181,13 +1176,15 @@
         return res;
     }
 
-    void setAppIdleAsync(String packageName, boolean idle, int userId) {
+    @Override
+    public void setAppIdleAsync(String packageName, boolean idle, int userId) {
         if (packageName == null || !mAppIdleEnabled) return;
 
         mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
                 .sendToTarget();
     }
 
+    @Override
     @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId,
             long elapsedRealtime, boolean shouldObfuscateInstantApps) {
         if (!mAppIdleEnabled || (shouldObfuscateInstantApps
@@ -1200,18 +1197,21 @@
         }
     }
 
+    @Override
     public List<AppStandbyInfo> getAppStandbyBuckets(int userId) {
         synchronized (mAppIdleLock) {
             return mAppIdleHistory.getAppStandbyBuckets(userId, mAppIdleEnabled);
         }
     }
 
+    @VisibleForTesting
     void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
             int reason, long elapsedRealtime) {
         setAppStandbyBucket(packageName, userId, newBucket, reason, elapsedRealtime, false);
     }
 
-    void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
+    @Override
+    public void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
             int reason, long elapsedRealtime, boolean resetTimeout) {
         synchronized (mAppIdleLock) {
             // If the package is not installed, don't allow the bucket to be set.
@@ -1279,6 +1279,7 @@
         }
     }
 
+    @Override
     public void addActiveDeviceAdmin(String adminPkg, int userId) {
         synchronized (mActiveAdminApps) {
             Set<String> adminPkgs = mActiveAdminApps.get(userId);
@@ -1290,6 +1291,7 @@
         }
     }
 
+    @Override
     public void setActiveAdminApps(Set<String> adminPkgs, int userId) {
         synchronized (mActiveAdminApps) {
             if (adminPkgs == null) {
@@ -1300,6 +1302,7 @@
         }
     }
 
+    @Override
     public void onAdminDataAvailable() {
         mAdminDataAvailableLatch.countDown();
     }
@@ -1314,6 +1317,7 @@
         }
     }
 
+    @VisibleForTesting
     Set<String> getActiveAdminAppsForTest(int userId) {
         synchronized (mActiveAdminApps) {
             return mActiveAdminApps.get(userId);
@@ -1342,7 +1346,8 @@
         }
     }
 
-    void clearCarrierPrivilegedApps() {
+    @Override
+    public void clearCarrierPrivilegedApps() {
         if (DEBUG) {
             Slog.i(TAG, "Clearing carrier privileged apps list");
         }
@@ -1368,7 +1373,7 @@
         return packageName != null && packageName.equals(activeScorer);
     }
 
-    void informListeners(String packageName, int userId, int bucket, int reason,
+    private void informListeners(String packageName, int userId, int bucket, int reason,
             boolean userInteraction) {
         final boolean idle = bucket >= STANDBY_BUCKET_RARE;
         synchronized (mPackageAccessListeners) {
@@ -1381,7 +1386,7 @@
         }
     }
 
-    void informParoleStateChanged() {
+    private void informParoleStateChanged() {
         final boolean paroled = isParoledOrCharging();
         synchronized (mPackageAccessListeners) {
             for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
@@ -1390,13 +1395,15 @@
         }
     }
 
-    void flushToDisk(int userId) {
+    @Override
+    public void flushToDisk(int userId) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.writeAppIdleTimes(userId);
         }
     }
 
-    void flushDurationsToDisk() {
+    @Override
+    public void flushDurationsToDisk() {
         // Persist elapsed and screen on time. If this fails for whatever reason, the apps will be
         // considered not-idle, which is the safest outcome in such an event.
         synchronized (mAppIdleLock) {
@@ -1404,10 +1411,11 @@
         }
     }
 
-    boolean isDisplayOn() {
+    private boolean isDisplayOn() {
         return mInjector.isDefaultDisplayOn();
     }
 
+    @VisibleForTesting
     void clearAppIdleForPackage(String packageName, int userId) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.clearUsage(packageName, userId);
@@ -1431,7 +1439,8 @@
         }
     }
 
-    void initializeDefaultsForSystemApps(int userId) {
+    @Override
+    public void initializeDefaultsForSystemApps(int userId) {
         if (!mSystemServicesReady) {
             // Do it later, since SettingsProvider wasn't queried yet for app_standby_enabled
             mPendingInitializeDefaults = true;
@@ -1461,7 +1470,8 @@
         }
     }
 
-    void postReportContentProviderUsage(String name, String packageName, int userId) {
+    @Override
+    public void postReportContentProviderUsage(String name, String packageName, int userId) {
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = name;
         args.arg2 = packageName;
@@ -1470,23 +1480,27 @@
                 .sendToTarget();
     }
 
-    void postReportSyncScheduled(String packageName, int userId, boolean exempted) {
+    @Override
+    public void postReportSyncScheduled(String packageName, int userId, boolean exempted) {
         mHandler.obtainMessage(MSG_REPORT_SYNC_SCHEDULED, userId, exempted ? 1 : 0, packageName)
                 .sendToTarget();
     }
 
-    void postReportExemptedSyncStart(String packageName, int userId) {
+    @Override
+    public void postReportExemptedSyncStart(String packageName, int userId) {
         mHandler.obtainMessage(MSG_REPORT_EXEMPTED_SYNC_START, userId, 0, packageName)
                 .sendToTarget();
     }
 
-    void dumpUser(IndentingPrintWriter idpw, int userId, String pkg) {
+    @Override
+    public void dumpUser(IndentingPrintWriter idpw, int userId, String pkg) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.dump(idpw, userId, pkg);
         }
     }
 
-    void dumpState(String[] args, PrintWriter pw) {
+    @Override
+    public void dumpState(String[] args, PrintWriter pw) {
         synchronized (mAppIdleLock) {
             pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
                     + "): " + mCarrierPrivilegedApps);
diff --git a/api/current.txt b/api/current.txt
index 3ce043c..02e822e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -57410,7 +57410,7 @@
     method public boolean onPrivateIMECommand(String, android.os.Bundle);
     method public void onRestoreInstanceState(android.os.Parcelable);
     method public android.os.Parcelable onSaveInstanceState();
-    method protected void onSelectionChanged(int, int);
+    method @CallSuper protected void onSelectionChanged(int, int);
     method protected void onTextChanged(CharSequence, int, int, int);
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
diff --git a/api/system-current.txt b/api/system-current.txt
index a4e20cc..8875e79 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -24,6 +24,7 @@
     field public static final String BACKUP = "android.permission.BACKUP";
     field public static final String BIND_ATTENTION_SERVICE = "android.permission.BIND_ATTENTION_SERVICE";
     field public static final String BIND_AUGMENTED_AUTOFILL_SERVICE = "android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE";
+    field public static final String BIND_CELL_BROADCAST_SERVICE = "android.permission.BIND_CELL_BROADCAST_SERVICE";
     field @Deprecated public static final String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
     field public static final String BIND_CONTENT_CAPTURE_SERVICE = "android.permission.BIND_CONTENT_CAPTURE_SERVICE";
     field public static final String BIND_CONTENT_SUGGESTIONS_SERVICE = "android.permission.BIND_CONTENT_SUGGESTIONS_SERVICE";
@@ -6361,6 +6362,7 @@
     method public android.os.IBinder onBind(android.content.Intent);
     method @Nullable public float[][] onCalculateScores(@NonNull java.util.List<android.view.autofill.AutofillValue>, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>, @Nullable String, @Nullable android.os.Bundle, @Nullable java.util.Map, @Nullable java.util.Map);
     method @Deprecated @Nullable public float[][] onGetScores(@Nullable String, @Nullable android.os.Bundle, @NonNull java.util.List<android.view.autofill.AutofillValue>, @NonNull java.util.List<java.lang.String>);
+    field public static final String REQUIRED_ALGORITHM_CREDIT_CARD = "CREDIT_CARD";
     field public static final String REQUIRED_ALGORITHM_EDIT_DISTANCE = "EDIT_DISTANCE";
     field public static final String REQUIRED_ALGORITHM_EXACT_MATCH = "EXACT_MATCH";
     field public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
@@ -7303,6 +7305,14 @@
     method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int);
   }
 
+  public abstract class CellBroadcastService extends android.app.Service {
+    ctor public CellBroadcastService();
+    method @CallSuper public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onCdmaCellBroadcastSms(int, byte[]);
+    method public abstract void onGsmCellBroadcastSms(int, byte[]);
+    field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
+  }
+
   public final class DataFailCause {
     field public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219; // 0x8ab
     field public static final int ACCESS_BLOCK = 2087; // 0x827
diff --git a/api/test-current.txt b/api/test-current.txt
index a40cb92..5cf2d0b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5,6 +5,7 @@
     field public static final String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS";
     field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
     field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
+    field public static final String BIND_CELL_BROADCAST_SERVICE = "android.permission.BIND_CELL_BROADCAST_SERVICE";
     field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
     field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
     field public static final String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
@@ -2481,6 +2482,7 @@
   public abstract class AutofillFieldClassificationService extends android.app.Service {
     ctor public AutofillFieldClassificationService();
     method public android.os.IBinder onBind(android.content.Intent);
+    field public static final String REQUIRED_ALGORITHM_CREDIT_CARD = "CREDIT_CARD";
     field public static final String REQUIRED_ALGORITHM_EDIT_DISTANCE = "EDIT_DISTANCE";
     field public static final String REQUIRED_ALGORITHM_EXACT_MATCH = "EXACT_MATCH";
     field public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
@@ -2900,6 +2902,8 @@
   }
 
   public class PhoneStateListener {
+    method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
+    method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
     field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_CALL_EMERGENCY_NUMBER = 268435456; // 0x10000000
     field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_SMS_EMERGENCY_NUMBER = 536870912; // 0x20000000
   }
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index 42132ee..7d446a9 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -53,6 +53,8 @@
     if (gStatsService != nullptr) {
         gStatsService->Terminate();
     }
+    ALOGW("statsd terminated on receiving signal %d.", sig);
+    exit(1);
 }
 
 void registerSigHandler()
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 76ee9a6..460b9e0 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -1199,87 +1199,66 @@
 
     ConfigKey cfgKey1(uid, 12341);
     long timeBase1 = 1;
-    sp<StatsLogProcessor> processor =
+    sp<StatsLogProcessor> processor1 =
             CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
 
     // Metric 1 is not active.
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
-    auto it = processor->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor->mMetricsManagers.end());
+    EXPECT_EQ(1, processor1->mMetricsManagers.size());
+    auto it = processor1->mMetricsManagers.find(cfgKey1);
+    EXPECT_TRUE(it != processor1->mMetricsManagers.end());
     auto& metricsManager1 = it->second;
     EXPECT_TRUE(metricsManager1->isActive());
 
-    auto metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer1 = *metricIt;
-    EXPECT_FALSE(metricProducer1->isActive());
+    EXPECT_EQ(metricsManager1->mAllMetricProducers.size(), 2);
+    // We assume that the index of a MetricProducer within the mAllMetricProducers
+    // array follows the order in which metrics are added to the config.
+    auto& metricProducer1_1 = metricsManager1->mAllMetricProducers[0];
+    EXPECT_EQ(metricProducer1_1->getMetricId(), metricId1);
+    EXPECT_FALSE(metricProducer1_1->isActive());  // inactive due to associated MetricActivation
 
-    metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer2 = *metricIt;
-    EXPECT_TRUE(metricProducer2->isActive());
+    auto& metricProducer1_2 = metricsManager1->mAllMetricProducers[1];
+    EXPECT_EQ(metricProducer1_2->getMetricId(), metricId2);
+    EXPECT_TRUE(metricProducer1_2->isActive());
 
-    int i = 0;
-    for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activation1 = metricProducer1->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kNotActive, activation1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1->activationType);
+    EXPECT_EQ(metricProducer1_1->mEventActivationMap.size(), 2);
+    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+    // that matchers are indexed in the order that they are added to the config.
+    const auto& activation1_1_1 = metricProducer1_1->mEventActivationMap.at(0);
+    EXPECT_EQ(100 * NS_PER_SEC, activation1_1_1->ttl_ns);
+    EXPECT_EQ(0, activation1_1_1->start_ns);
+    EXPECT_EQ(kNotActive, activation1_1_1->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1_1_1->activationType);
 
-    i = 0;
-    for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activation2 = metricProducer1->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
-    EXPECT_EQ(0, activation2->start_ns);
-    EXPECT_EQ(kNotActive, activation2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2->activationType);
+    const auto& activation1_1_2 = metricProducer1_1->mEventActivationMap.at(1);
+    EXPECT_EQ(200 * NS_PER_SEC, activation1_1_2->ttl_ns);
+    EXPECT_EQ(0, activation1_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation1_1_2->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1_1_2->activationType);
     // }}}------------------------------------------------------------------------------
 
     // Trigger Activation 1 for Metric 1
     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
     auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
-    processor->OnLogEvent(event.get());
+    processor1->OnLogEvent(event.get());
 
     // Metric 1 is not active; Activation 1 set to kActiveOnBoot
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_FALSE(metricProducer1->isActive());
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kActiveOnBoot, activation1->state);
-    EXPECT_EQ(0, activation2->start_ns);
-    EXPECT_EQ(kNotActive, activation2->state);
+    EXPECT_FALSE(metricProducer1_1->isActive());
+    EXPECT_EQ(0, activation1_1_1->start_ns);
+    EXPECT_EQ(kActiveOnBoot, activation1_1_1->state);
+    EXPECT_EQ(0, activation1_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation1_1_2->state);
 
-    EXPECT_TRUE(metricProducer2->isActive());
+    EXPECT_TRUE(metricProducer1_2->isActive());
     // }}}-----------------------------------------------------------------------------
 
     // Simulate shutdown by saving state to disk
     int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
-    processor->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_FALSE(metricProducer1->isActive());
-    int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
+    processor1->SaveActiveConfigsToDisk(shutDownTime);
+    EXPECT_FALSE(metricProducer1_1->isActive());
 
     // Simulate device restarted state by creating new instance of StatsLogProcessor with the
     // same config.
@@ -1293,55 +1272,34 @@
     EXPECT_EQ(1, processor2->mMetricsManagers.size());
     it = processor2->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor2->mMetricsManagers.end());
-    auto& metricsManager1001 = it->second;
-    EXPECT_TRUE(metricsManager1001->isActive());
+    auto& metricsManager2 = it->second;
+    EXPECT_TRUE(metricsManager2->isActive());
 
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1001 = *metricIt;
-    EXPECT_FALSE(metricProducer1001->isActive());
+    EXPECT_EQ(metricsManager2->mAllMetricProducers.size(), 2);
+    // We assume that the index of a MetricProducer within the mAllMetricProducers
+    // array follows the order in which metrics are added to the config.
+    auto& metricProducer2_1 = metricsManager2->mAllMetricProducers[0];
+    EXPECT_EQ(metricProducer2_1->getMetricId(), metricId1);
+    EXPECT_FALSE(metricProducer2_1->isActive());
 
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1002 = *metricIt;
-    EXPECT_TRUE(metricProducer1002->isActive());
+    auto& metricProducer2_2 = metricsManager2->mAllMetricProducers[1];
+    EXPECT_EQ(metricProducer2_2->getMetricId(), metricId2);
+    EXPECT_TRUE(metricProducer2_2->isActive());
 
-    i = 0;
-    for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activation1001_1 = metricProducer1001->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1001_1->ttl_ns);
-    EXPECT_EQ(0, activation1001_1->start_ns);
-    EXPECT_EQ(kNotActive, activation1001_1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1001_1->activationType);
+    EXPECT_EQ(metricProducer2_1->mEventActivationMap.size(), 2);
+    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+    // that matchers are indexed in the order that they are added to the config.
+    const auto& activation2_1_1 = metricProducer2_1->mEventActivationMap.at(0);
+    EXPECT_EQ(100 * NS_PER_SEC, activation2_1_1->ttl_ns);
+    EXPECT_EQ(0, activation2_1_1->start_ns);
+    EXPECT_EQ(kNotActive, activation2_1_1->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation2_1_1->activationType);
 
-    i = 0;
-    for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-
-    const auto& activation1001_2 = metricProducer1001->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activation1001_2->ttl_ns);
-    EXPECT_EQ(0, activation1001_2->start_ns);
-    EXPECT_EQ(kNotActive, activation1001_2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1001_2->activationType);
+    const auto& activation2_1_2 = metricProducer2_1->mEventActivationMap.at(1);
+    EXPECT_EQ(200 * NS_PER_SEC, activation2_1_2->ttl_ns);
+    EXPECT_EQ(0, activation2_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation2_1_2->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2_1_2->activationType);
     // }}}-----------------------------------------------------------------------------------
 
     // Load saved state from disk.
@@ -1350,13 +1308,14 @@
     // Metric 1 active; Activation 1 is active, Activation 2 is not active
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
-    EXPECT_EQ(kActive, activation1001_1->state);
-    EXPECT_EQ(0, activation1001_2->start_ns);
-    EXPECT_EQ(kNotActive, activation1001_2->state);
+    EXPECT_TRUE(metricProducer2_1->isActive());
+    int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
+    EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
+    EXPECT_EQ(kActive, activation2_1_1->state);
+    EXPECT_EQ(0, activation2_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation2_1_2->state);
 
-    EXPECT_TRUE(metricProducer1002->isActive());
+    EXPECT_TRUE(metricProducer2_2->isActive());
     // }}}--------------------------------------------------------------------------------
 
     // Trigger Activation 2 for Metric 1.
@@ -1369,23 +1328,23 @@
     // Metric 1 active; Activation 1 is active, Activation 2 is active
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
-    EXPECT_EQ(kActive, activation1001_1->state);
-    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation1001_2->start_ns);
-    EXPECT_EQ(kActive, activation1001_2->state);
+    EXPECT_TRUE(metricProducer2_1->isActive());
+    EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
+    EXPECT_EQ(kActive, activation2_1_1->state);
+    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation2_1_2->start_ns);
+    EXPECT_EQ(kActive, activation2_1_2->state);
 
-    EXPECT_TRUE(metricProducer1002->isActive());
+    EXPECT_TRUE(metricProducer2_2->isActive());
     // }}}---------------------------------------------------------------------------
 
     // Simulate shutdown by saving state to disk
     shutDownTime = timeBase2 + 50 * NS_PER_SEC;
     processor2->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_TRUE(metricProducer1002->isActive());
-    ttl1 = timeBase2 + metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC - shutDownTime;
-    int64_t ttl2 = screenOnEvent->GetElapsedTimestampNs() +
-            metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC - shutDownTime;
+    EXPECT_TRUE(metricProducer2_1->isActive());
+    EXPECT_TRUE(metricProducer2_2->isActive());
+    ttl1 -= shutDownTime - timeBase2;
+    int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC
+            - (shutDownTime - screenOnEvent->GetElapsedTimestampNs());
 
     // Simulate device restarted state by creating new instance of StatsLogProcessor with the
     // same config.
@@ -1399,55 +1358,34 @@
     EXPECT_EQ(1, processor3->mMetricsManagers.size());
     it = processor3->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor3->mMetricsManagers.end());
-    auto& metricsManagerTimeBase3 = it->second;
-    EXPECT_TRUE(metricsManagerTimeBase3->isActive());
+    auto& metricsManager3 = it->second;
+    EXPECT_TRUE(metricsManager3->isActive());
 
-    metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
-    for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
-    auto& metricProducerTimeBase3_1 = *metricIt;
-    EXPECT_FALSE(metricProducerTimeBase3_1->isActive());
+    EXPECT_EQ(metricsManager3->mAllMetricProducers.size(), 2);
+    // We assume that the index of a MetricProducer within the mAllMetricProducers
+    // array follows the order in which metrics are added to the config.
+    auto& metricProducer3_1 = metricsManager3->mAllMetricProducers[0];
+    EXPECT_EQ(metricProducer3_1->getMetricId(), metricId1);
+    EXPECT_FALSE(metricProducer3_1->isActive());
 
-    metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
-    for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
-    auto& metricProducerTimeBase3_2 = *metricIt;
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+    auto& metricProducer3_2 = metricsManager3->mAllMetricProducers[1];
+    EXPECT_EQ(metricProducer3_2->getMetricId(), metricId2);
+    EXPECT_TRUE(metricProducer3_2->isActive());
 
-    i = 0;
-    for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
-        if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activationTimeBase3_1 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase3_1->ttl_ns);
-    EXPECT_EQ(0, activationTimeBase3_1->start_ns);
-    EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activationTimeBase3_1->activationType);
+    EXPECT_EQ(metricProducer3_1->mEventActivationMap.size(), 2);
+    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+    // that matchers are indexed in the order that they are added to the config.
+    const auto& activation3_1_1 = metricProducer3_1->mEventActivationMap.at(0);
+    EXPECT_EQ(100 * NS_PER_SEC, activation3_1_1->ttl_ns);
+    EXPECT_EQ(0, activation3_1_1->start_ns);
+    EXPECT_EQ(kNotActive, activation3_1_1->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation3_1_1->activationType);
 
-    i = 0;
-    for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
-        if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-
-    const auto& activationTimeBase3_2 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase3_2->ttl_ns);
-    EXPECT_EQ(0, activationTimeBase3_2->start_ns);
-    EXPECT_EQ(kNotActive, activationTimeBase3_2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activationTimeBase3_2->activationType);
+    const auto& activation3_1_2 = metricProducer3_1->mEventActivationMap.at(1);
+    EXPECT_EQ(200 * NS_PER_SEC, activation3_1_2->ttl_ns);
+    EXPECT_EQ(0, activation3_1_2->start_ns);
+    EXPECT_EQ(kNotActive, activation3_1_2->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation3_1_2->activationType);
     // }}}----------------------------------------------------------------------------------
 
     // Load saved state from disk.
@@ -1456,13 +1394,13 @@
     // Metric 1 active: Activation 1 is active, Activation 2 is active
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
-    EXPECT_EQ(timeBase3 + ttl1 - activationTimeBase3_1->ttl_ns, activationTimeBase3_1->start_ns);
-    EXPECT_EQ(kActive, activationTimeBase3_1->state);
-    EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
-    EXPECT_EQ(kActive, activationTimeBase3_2->state);
+    EXPECT_TRUE(metricProducer3_1->isActive());
+    EXPECT_EQ(timeBase3 + ttl1 - activation3_1_1->ttl_ns, activation3_1_1->start_ns);
+    EXPECT_EQ(kActive, activation3_1_1->state);
+    EXPECT_EQ(timeBase3 + ttl2 - activation3_1_2->ttl_ns, activation3_1_2->start_ns);
+    EXPECT_EQ(kActive, activation3_1_2->state);
 
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+    EXPECT_TRUE(metricProducer3_2->isActive());
     // }}}-------------------------------------------------------------------------------
 
 
@@ -1473,15 +1411,16 @@
     );
     processor3->OnLogEvent(screenOnEvent.get());
 
-    // Metric 1 active; Activation 1 is not active, Activation 2 is set to active
+    // Metric 1 active; Activation 1 is inactive (above screenOnEvent causes ttl1 to expire),
+    //                  Activation 2 is set to active
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
-    EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
-    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activationTimeBase3_2->start_ns);
-    EXPECT_EQ(kActive, activationTimeBase3_2->state);
+    EXPECT_TRUE(metricProducer3_1->isActive());
+    EXPECT_EQ(kNotActive, activation3_1_1->state);
+    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation3_1_2->start_ns);
+    EXPECT_EQ(kActive, activation3_1_2->state);
 
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+    EXPECT_TRUE(metricProducer3_2->isActive());
     // }}}---------------------------------------------------------------------------
 }
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 0499337..e81dc1c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1343,13 +1343,13 @@
      * @hide
      */
     public static <T> void registerCachedService(String serviceName, Class<T> serviceWrapperClass,
-            BiFunction<ContextImpl, IBinder, T> serviceFetcher) {
+            BiFunction<Context, IBinder, T> serviceFetcher) {
         registerService(serviceName, serviceWrapperClass,
                 new CachedServiceFetcher<T>() {
                     @Override
                     public T createService(ContextImpl ctx) throws ServiceNotFoundException {
                         IBinder b = ServiceManager.getServiceOrThrow(serviceName);
-                        return serviceFetcher.apply(ctx, b);
+                        return serviceFetcher.apply(ctx.getOuterContext(), b);
                     }});
     }
 
diff --git a/core/java/android/app/role/IRoleManager.aidl b/core/java/android/app/role/IRoleManager.aidl
index d8cea28..6d790b3 100644
--- a/core/java/android/app/role/IRoleManager.aidl
+++ b/core/java/android/app/role/IRoleManager.aidl
@@ -19,7 +19,6 @@
 import android.app.role.IOnRoleHoldersChangedListener;
 import android.os.Bundle;
 import android.os.RemoteCallback;
-import android.telephony.IFinancialSmsCallback;
 
 /**
  * @hide
@@ -55,9 +54,4 @@
     List<String> getHeldRolesFromController(in String packageName);
 
     String getDefaultSmsPackage(int userId);
-
-    /**
-     * Get filtered SMS messages for financial app.
-     */
-    void getSmsMessagesForFinancialApp(in String callingPkg, in Bundle params, in IFinancialSmsCallback callback);
 }
diff --git a/core/java/android/app/usage/AppStandbyInfo.java b/core/java/android/app/usage/AppStandbyInfo.java
index ebdbf83..c283702 100644
--- a/core/java/android/app/usage/AppStandbyInfo.java
+++ b/core/java/android/app/usage/AppStandbyInfo.java
@@ -22,6 +22,10 @@
 /**
  * A pair of {package, bucket} to denote the app standby bucket for a given package.
  * Used as a vehicle of data across the binder IPC.
+ *
+ * Note we're not moving this class to the jobscheduler apex, because it's consumed by
+ * UsageStatsManager, which is not updatable anyway, so making this updatable isn't really
+ * beneficial.
  * @hide
  */
 public final class AppStandbyInfo implements Parcelable {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 802c1a0a..08817e0 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3301,7 +3301,7 @@
      *  <dt> {@link #VIBRATOR_SERVICE} ("vibrator")
      *  <dd> A {@link android.os.Vibrator} for interacting with the vibrator
      *  hardware.
-     *  <dt> {@link #CONNECTIVITY_SERVICE} ("connection")
+     *  <dt> {@link #CONNECTIVITY_SERVICE} ("connectivity")
      *  <dd> A {@link android.net.ConnectivityManager ConnectivityManager} for
      *  handling management of network connections.
      *  <dt> {@link #IPSEC_SERVICE} ("ipsec")
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index e24512a..c3daad1 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -16,8 +16,6 @@
 
 package android.content;
 
-import static android.app.AppOpsManager.strOpToOp;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -52,6 +50,19 @@
  * permission model for which the user had disabled the "permission"
  * which is achieved by disallowing the corresponding app op.
  * </p>
+ * <p>
+ * This class has two types of methods and you should be careful which
+ * type to call based on whether permission protected data is being
+ * passed to the app or you are just checking whether the app holds a
+ * permission. The reason is that a permission check requires checking
+ * the runtime permission and if it is granted checking the corresponding
+ * app op as for apps not supporting the runtime mode we never revoke
+ * permissions but disable app ops. Since there are two types of app op
+ * checks, one that does not leave a record an action was performed and
+ * another the does, one needs to call the preflight flavor of the checks
+ * named xxxForPreflight only if no private data is being delivered but
+ * a permission check is what is needed and the xxxForDataDelivery where
+ * the permission check is right before private data delivery.
  *
  * @hide
  */
@@ -65,6 +76,9 @@
     /** Permission result: The permission is denied because the app op is not allowed. */
     public static final int PERMISSION_DENIED_APP_OP =  PackageManager.PERMISSION_DENIED  - 1;
 
+    /** Constant when the PID for which we check permissions is unknown. */
+    public static final int PID_UNKNOWN = -1;
+
     /** @hide */
     @IntDef({PERMISSION_GRANTED,
             PERMISSION_DENIED,
@@ -77,33 +91,297 @@
     }
 
     /**
-     * @deprecated Use {@link #checkPermission(Context, String, int, int, String, String)} instead
+     * Checks whether a given package in a UID and PID has a given permission
+     * and whether the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
+     *    is not known.
+     * @param uid The uid for which to check.
+     * @param packageName The package name for which to check. If null the
+     *     the first package for the calling UID will be used.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkPermissionForPreflight(Context, String, int, int, String)
      */
-    @Deprecated
     @PermissionResult
-    public static int checkPermission(@NonNull Context context, @NonNull String permission,
-            int pid, int uid, @Nullable String packageName) {
-        return checkPermission(context, permission, pid, uid, packageName, null);
+    public static int checkPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, int pid, int uid, @Nullable String packageName,
+            @Nullable String message) {
+        return checkPermissionCommon(context, permission, pid, uid, packageName, message,
+                true /*forDataDelivery*/);
     }
 
     /**
      * Checks whether a given package in a UID and PID has a given permission
      * and whether the app op that corresponds to this permission is allowed.
      *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * preflight point where you will not deliver the permission protected data
+     * to clients but schedule permission data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have location
+     * permission (if app has only foreground location the grant state depends on the app's
+     * fg/gb state) and this check will not leave a trace that permission protected data
+     * was delivered. When you are about to deliver the location data to a registered
+     * listener you should use {@link #checkPermissionForDataDelivery(Context, String,
+     * int, int, String, String)} which will evaluate the permission access based on the current
+     * fg/bg state of the app and leave a record that the data was accessed.
+     *
      * @param context Context for accessing resources.
      * @param permission The permission to check.
      * @param pid The process id for which to check.
      * @param uid The uid for which to check.
      * @param packageName The package name for which to check. If null the
      *     the first package for the calling UID will be used.
-     * @param message A message describing the reason the permission was checked
-     *
      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
      *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     *
+     * @see #checkPermissionForDataDelivery(Context, String, int, int, String, String)
      */
     @PermissionResult
-    public static int checkPermission(@NonNull Context context, @NonNull String permission,
-            int pid, int uid, @Nullable String packageName, @Nullable String message) {
+    public static int checkPermissionForPreflight(@NonNull Context context,
+            @NonNull String permission, int pid, int uid, @Nullable String packageName) {
+        return checkPermissionCommon(context, permission, pid, uid, packageName, null /*message*/,
+                false /*forDataDelivery*/);
+    }
+
+    /**
+     * Checks whether your app has a given permission and whether the app op
+     * that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkSelfPermissionForPreflight(Context, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method
+     * which will evaluate the permission access based on the current fg/bg state of the
+     * app and leave a record that the data was accessed.
+     *
+     * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as
+     * {@link Process#myUid()}.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkSelfPermissionForPreflight(Context, String)
+     */
+    @PermissionResult
+    public static int checkSelfPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, @Nullable String message) {
+        return checkPermissionForDataDelivery(context, permission, Process.myPid(),
+                Process.myUid(), context.getPackageName(), message);
+    }
+
+    /**
+     * Checks whether your app has a given permission and whether the app op
+     * that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * preflight point where you will not deliver the permission protected data
+     * to clients but schedule permission data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have location
+     * permission (if app has only foreground location the grant state depends on the
+     * app's fg/gb state) and this check will not leave a trace that permission protected
+     * data was delivered. When you are about to deliver the location data to a registered
+     * listener you should use this method which will evaluate the permission access based
+     * on the current fg/bg state of the app and leave a record that the data was accessed.
+     *
+     * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as
+     * {@link Process#myUid()}.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     *
+     * @see #checkSelfPermissionForDataDelivery(Context, String, String)
+     */
+    @PermissionResult
+    public static int checkSelfPermissionForPreflight(@NonNull Context context,
+            @NonNull String permission) {
+        return checkPermissionForPreflight(context, permission, Process.myPid(),
+                Process.myUid(), context.getPackageName());
+    }
+
+    /**
+     * Checks whether the IPC you are handling has a given permission and whether
+     * the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkCallingPermissionForPreflight(Context, String, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param packageName The package name making the IPC. If null the
+     *     the first package for the calling UID will be used.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkCallingPermissionForPreflight(Context, String, String)
+     */
+    @PermissionResult
+    public static int checkCallingPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, @Nullable String packageName, @Nullable String message) {
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return PERMISSION_DENIED;
+        }
+        return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
+                Binder.getCallingUid(), packageName, message);
+    }
+
+    /**
+     * Checks whether the IPC you are handling has a given permission and whether
+     * the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * preflight point where you will not deliver the permission protected data
+     * to clients but schedule permission data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have location
+     * permission (if app has only foreground location the grant state depends on the app's
+     * fg/gb state) and this check will not leave a trace that permission protected data
+     * was delivered. When you are about to deliver the location data to a registered
+     * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
+     * String, String)} which will evaluate the permission access based on the current fg/bg state
+     * of the app and leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param packageName The package name making the IPC. If null the
+     *     the first package for the calling UID will be used.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     *
+     * @see #checkCallingPermissionForDataDelivery(Context, String, String, String)
+     */
+    @PermissionResult
+    public static int checkCallingPermissionForPreflight(@NonNull Context context,
+            @NonNull String permission, @Nullable String packageName) {
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return PERMISSION_DENIED;
+        }
+        return checkPermissionForPreflight(context, permission, Binder.getCallingPid(),
+                Binder.getCallingUid(), packageName);
+    }
+
+    /**
+     * Checks whether the IPC you are handling or your app has a given permission
+     * and whether the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * point where you will deliver the permission protected data to clients.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use {@link #checkCallingOrSelfPermissionForPreflight(Context, String)}
+     * to determine if the app has or may have location permission (if app has only foreground
+     * location the grant state depends on the app's fg/gb state) and this check will not
+     * leave a trace that permission protected data was delivered. When you are about to
+     * deliver the location data to a registered listener you should use this method which
+     * will evaluate the permission access based on the current fg/bg state of the app and
+     * leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     * @param message A message describing the reason the permission was checked
+     *
+     * @see #checkCallingOrSelfPermissionForPreflight(Context, String)
+     */
+    @PermissionResult
+    public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context,
+            @NonNull String permission, @Nullable String message) {
+        String packageName = (Binder.getCallingPid() == Process.myPid())
+                ? context.getPackageName() : null;
+        return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
+                Binder.getCallingUid(), packageName, message);
+    }
+
+    /**
+     * Checks whether the IPC you are handling or your app has a given permission
+     * and whether the app op that corresponds to this permission is allowed.
+     *
+     * <strong>NOTE:</strong> Use this method only for permission checks at the
+     * preflight point where you will not deliver the permission protected data
+     * to clients but schedule permission data delivery, apps register listeners,
+     * etc.
+     *
+     * <p>For example, if an app registers a location listener it should have the location
+     * permission but no data is actually sent to the app at the moment of registration
+     * and you should use this method to determine if the app has or may have location
+     * permission (if app has only foreground location the grant state depends on the
+     * app's fg/gb state) and this check will not leave a trace that permission protected
+     * data was delivered. When you are about to deliver the location data to a registered
+     * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
+     * String, String)} which will evaluate the permission access based on the current fg/bg state
+     * of the app and leave a record that the data was accessed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     *
+     * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String)
+     */
+    @PermissionResult
+    public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context,
+            @NonNull String permission) {
+        String packageName = (Binder.getCallingPid() == Process.myPid())
+                ? context.getPackageName() : null;
+        return checkPermissionForPreflight(context, permission, Binder.getCallingPid(),
+                Binder.getCallingUid(), packageName);
+    }
+
+    private static int checkPermissionCommon(@NonNull Context context, @NonNull String permission,
+            int pid, int uid, @Nullable String packageName, @Nullable String message,
+            boolean forDataDelivery) {
         if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
             return PERMISSION_DENIED;
         }
@@ -122,93 +400,18 @@
             packageName = packageNames[0];
         }
 
-        if (appOpsManager.noteProxyOpNoThrow(strOpToOp(op), packageName, uid, message)
-                != AppOpsManager.MODE_ALLOWED) {
-            return PERMISSION_DENIED_APP_OP;
+        if (forDataDelivery) {
+            if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid, message)
+                    != AppOpsManager.MODE_ALLOWED) {
+                return PERMISSION_DENIED_APP_OP;
+            }
+        } else {
+            final int mode = appOpsManager.unsafeCheckOpRawNoThrow(op, uid, packageName);
+            if (mode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_FOREGROUND) {
+                return PERMISSION_DENIED_APP_OP;
+            }
         }
 
         return PERMISSION_GRANTED;
     }
-
-    /**
-     * Checks whether your app has a given permission and whether the app op
-     * that corresponds to this permission is allowed.
-     *
-     * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as
-     * {@link Process#myUid()}.
-     *
-     * @param context Context for accessing resources.
-     * @param permission The permission to check.
-     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
-     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
-     */
-    @PermissionResult
-    public static int checkSelfPermission(@NonNull Context context,
-            @NonNull String permission) {
-        return checkPermission(context, permission, Process.myPid(),
-                Process.myUid(), context.getPackageName(), null /* self access */);
-    }
-
-    /**
-     * @deprecated Use {@link #checkCallingPermission(Context, String, String, String)} instead
-     */
-    @Deprecated
-    @PermissionResult
-    public static int checkCallingPermission(@NonNull Context context,
-            @NonNull String permission, @Nullable String packageName) {
-        return checkCallingPermission(context, permission, packageName, null);
-    }
-
-    /**
-     * Checks whether the IPC you are handling has a given permission and whether
-     * the app op that corresponds to this permission is allowed.
-     *
-     * @param context Context for accessing resources.
-     * @param permission The permission to check.
-     * @param packageName The package name making the IPC. If null the
-     *     the first package for the calling UID will be used.
-     * @param message A message describing the reason the permission was checked
-     *
-     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
-     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
-     */
-    @PermissionResult
-    public static int checkCallingPermission(@NonNull Context context,
-            @NonNull String permission, @Nullable String packageName, @Nullable String message) {
-        if (Binder.getCallingPid() == Process.myPid()) {
-            return PERMISSION_DENIED;
-        }
-        return checkPermission(context, permission, Binder.getCallingPid(),
-                Binder.getCallingUid(), packageName, message);
-    }
-
-    /**
-     * @deprecated Use {@link #checkCallingOrSelfPermission(Context, String, String)} instead
-     */
-    @Deprecated
-    @PermissionResult
-    public static int checkCallingOrSelfPermission(@NonNull Context context,
-            @NonNull String permission) {
-        return checkCallingOrSelfPermission(context, permission, null);
-    }
-
-    /**
-     * Checks whether the IPC you are handling or your app has a given permission
-     * and whether the app op that corresponds to this permission is allowed.
-     *
-     * @param context Context for accessing resources.
-     * @param permission The permission to check.
-     * @param message A message describing the reason the permission was checked
-     *
-     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
-     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
-     */
-    @PermissionResult
-    public static int checkCallingOrSelfPermission(@NonNull Context context,
-            @NonNull String permission, @Nullable String message) {
-        String packageName = (Binder.getCallingPid() == Process.myPid())
-                ? context.getPackageName() : null;
-        return checkPermission(context, permission, Binder.getCallingPid(),
-                Binder.getCallingUid(), packageName, message);
-    }
-}
+}
\ No newline at end of file
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 0a99142..9f0bade 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -420,10 +420,10 @@
         lastLoggedInTime = source.readLong();
         lastLoggedInFingerprint = source.readString();
         partial = source.readBoolean();
+        preCreated = source.readBoolean();
         profileGroupId = source.readInt();
         guestToRemove = source.readBoolean();
         restrictedProfileParentId = source.readInt();
         profileBadge = source.readInt();
-        preCreated = source.readBoolean();
     }
 }
diff --git a/core/java/android/hardware/location/ContextHubClientCallback.java b/core/java/android/hardware/location/ContextHubClientCallback.java
index cc2fe65..20fa753 100644
--- a/core/java/android/hardware/location/ContextHubClientCallback.java
+++ b/core/java/android/hardware/location/ContextHubClientCallback.java
@@ -66,7 +66,9 @@
     public void onNanoAppAborted(ContextHubClient client, long nanoAppId, int abortCode) {}
 
     /**
-     * Callback invoked when a nanoapp is loaded at the attached Context Hub.
+     * Callback invoked when a nanoapp is dynamically loaded at the attached Context Hub through
+     * the {@link android.hardware.location.ContextHubManager}. This callback is not invoked for a
+     * nanoapp that is loaded internally by CHRE (e.g. nanoapps that are preloaded by the system).
      *
      * @param client the client that is associated with this callback
      * @param nanoAppId the ID of the nanoapp that had been loaded
@@ -74,7 +76,8 @@
     public void onNanoAppLoaded(ContextHubClient client, long nanoAppId) {}
 
     /**
-     * Callback invoked when a nanoapp is unloaded from the attached Context Hub.
+     * Callback invoked when a nanoapp is dynamically unloaded from the attached Context Hub through
+     * the {@link android.hardware.location.ContextHubManager}.
      *
      * @param client the client that is associated with this callback
      * @param nanoAppId the ID of the nanoapp that had been unloaded
@@ -82,7 +85,8 @@
     public void onNanoAppUnloaded(ContextHubClient client, long nanoAppId) {}
 
     /**
-     * Callback invoked when a nanoapp is enabled at the attached Context Hub.
+     * Callback invoked when a nanoapp is dynamically enabled at the attached Context Hub through
+     * the {@link android.hardware.location.ContextHubManager}.
      *
      * @param client the client that is associated with this callback
      * @param nanoAppId the ID of the nanoapp that had been enabled
@@ -90,7 +94,8 @@
     public void onNanoAppEnabled(ContextHubClient client, long nanoAppId) {}
 
     /**
-     * Callback invoked when a nanoapp is disabled at the attached Context Hub.
+     * Callback invoked when a nanoapp is dynamically disabled at the attached Context Hub through
+     * the {@link android.hardware.location.ContextHubManager}.
      *
      * @param client the client that is associated with this callback
      * @param nanoAppId the ID of the nanoapp that had been disabled
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
index 320dcec6..28842a7 100644
--- a/core/java/android/service/autofill/AutofillFieldClassificationService.java
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -93,6 +93,13 @@
      */
     public static final String REQUIRED_ALGORITHM_EXACT_MATCH = "EXACT_MATCH";
 
+    /**
+     * Field classification algorithm that compares a credit card string to known last four digits.
+     *
+     * <p>Service implementation must provide this algorithm.</p>
+     */
+    public static final String REQUIRED_ALGORITHM_CREDIT_CARD = "CREDIT_CARD";
+
     /** {@hide} **/
     public static final String EXTRA_SCORES = "scores";
 
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 70dfef5..dfc5c82 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -170,13 +170,23 @@
      * Checks whether the caller has sufficient permissions
      * 
      * @param listener to send the error message to in case of error
+     * @param forDataDelivery If the permission check is for delivering the sensitive data.
      * @return {@code true} if the caller has enough permissions, {@code false} otherwise
      */
-    private boolean checkPermissions(IRecognitionListener listener) {
+    private boolean checkPermissions(IRecognitionListener listener, boolean forDataDelivery) {
         if (DBG) Log.d(TAG, "checkPermissions");
-        if (PermissionChecker.checkCallingOrSelfPermission(this,
-                android.Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) {
-            return true;
+        if (forDataDelivery) {
+            if (PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(this,
+                    android.Manifest.permission.RECORD_AUDIO, null /*message*/)
+                             == PermissionChecker.PERMISSION_GRANTED) {
+                return true;
+            }
+        } else {
+            if (PermissionChecker.checkCallingOrSelfPermissionForPreflight(this,
+                    android.Manifest.permission.RECORD_AUDIO)
+                            == PermissionChecker.PERMISSION_GRANTED) {
+                return true;
+            }
         }
         try {
             Log.e(TAG, "call for recognition service without RECORD_AUDIO permissions");
@@ -342,7 +352,7 @@
         public void startListening(Intent recognizerIntent, IRecognitionListener listener) {
             if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
             final RecognitionService service = mServiceRef.get();
-            if (service != null && service.checkPermissions(listener)) {
+            if (service != null && service.checkPermissions(listener, true /*forDataDelivery*/)) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
                         MSG_START_LISTENING, service.new StartListeningArgs(
                                 recognizerIntent, listener, Binder.getCallingUid())));
@@ -353,7 +363,7 @@
         public void stopListening(IRecognitionListener listener) {
             if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
             final RecognitionService service = mServiceRef.get();
-            if (service != null && service.checkPermissions(listener)) {
+            if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
                         MSG_STOP_LISTENING, listener));
             }
@@ -363,7 +373,7 @@
         public void cancel(IRecognitionListener listener) {
             if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
             final RecognitionService service = mServiceRef.get();
-            if (service != null && service.checkPermissions(listener)) {
+            if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) {
                 service.mHandler.sendMessage(Message.obtain(service.mHandler,
                         MSG_CANCEL, listener));
             }
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index fc23c54..358fdc7 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -19,7 +19,7 @@
 import android.annotation.Nullable;
 import android.text.TextUtils;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.util.regex.Pattern;
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f997d68..31f5055 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -23,6 +23,7 @@
 import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
 
 import android.R;
+import android.annotation.CallSuper;
 import android.annotation.CheckResult;
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
@@ -10446,10 +10447,15 @@
     /**
      * This method is called when the selection has changed, in case any
      * subclasses would like to know.
+     * </p>
+     * <p class="note"><strong>Note:</strong> Always call the super implementation, which informs
+     * the accessibility subsystem about the selection change.
+     * </p>
      *
      * @param selStart The new selection start location.
      * @param selEnd The new selection end location.
      */
+    @CallSuper
     protected void onSelectionChanged(int selStart, int selEnd) {
         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
     }
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index e415b41..4d8378a 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -43,11 +43,6 @@
     /**
      * Reports that a compatibility change is affecting an app process now.
      *
-     * <p>Same as {@link #reportChange(long, ApplicationInfo)}, except it receives a package name
-     * instead of an {@link ApplicationInfo}
-     * object, and finds an app info object based on the package name. Returns {@code true} if
-     * there is no installed package by that name.
-     *
      * <p>Note: for changes that are gated using {@link #isChangeEnabled(long, String)},
      * you do not need to call this API directly. The change will be reported for you.
      *
@@ -57,6 +52,17 @@
      void reportChangeByPackageName(long changeId, in String packageName);
 
     /**
+     * Reports that a compatibility change is affecting an app process now.
+     *
+     * <p>Note: for changes that are gated using {@link #isChangeEnabled(long, int)},
+     * you do not need to call this API directly. The change will be reported for you.
+     *
+     * @param changeId The ID of the compatibility change taking effect.
+     * @param uid      The UID of the app in question.
+     */
+    void reportChangeByUid(long changeId, int uid);
+
+    /**
      * Query if a given compatibility change is enabled for an app process. This method should
      * be called when implementing functionality on behalf of the affected app.
      *
@@ -95,4 +101,28 @@
      * @return {@code true} if the change is enabled for the current app.
      */
     boolean isChangeEnabledByPackageName(long changeId, in String packageName);
+
+    /**
+     * Query if a given compatibility change is enabled for an app process. This method should
+     * be called when implementing functionality on behalf of the affected app.
+     *
+     * <p>Same as {@link #isChangeEnabled(long, ApplicationInfo)}, except it receives a uid
+     * instead of an {@link ApplicationInfo} object, and finds an app info object based on the
+     * uid (or objects if there's more than one package associated with the UID).
+     * Returns {@code true} if there are no installed packages for the required UID, or if the
+     * change is enabled for ALL of the installed packages associated with the provided UID. Please
+     * use a more specific API if you want a different behaviour for multi-package UIDs.
+     *
+     * <p>If this method returns {@code true}, the calling code should implement the compatibility
+     * change, resulting in differing behaviour compared to earlier releases. If this method
+     * returns {@code false}, the calling code should behave as it did in earlier releases.
+     *
+     * <p>It will also report the change as {@link #reportChange(long, int)} would, so there is
+     * no need to call that method directly.
+     *
+     * @param changeId The ID of the compatibility change in question.
+     * @param uid      The UID of the app in question.
+     * @return {@code true} if the change is enabled for the current app.
+     */
+    boolean isChangeEnabledByUid(long changeId, int uid);
 }
\ No newline at end of file
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 9fff447..fd3cd42 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -35,7 +35,7 @@
 import dalvik.system.RuntimeHooks;
 import dalvik.system.VMRuntime;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -203,13 +203,15 @@
     public static void preForkInit() {
         if (DEBUG) Slog.d(TAG, "Entered preForkInit.");
         RuntimeInit.enableDdms();
+        // TODO(b/142019040#comment13): Decide whether to load the default instance eagerly, i.e.
+        // MimeMap.setDefault(DefaultMimeMapFactory.create());
         /*
          * Replace libcore's minimal default mapping between MIME types and file
          * extensions with a mapping that's suitable for Android. Android's mapping
          * contains many more entries that are derived from IANA registrations but
          * with several customizations (extensions, overrides).
          */
-        MimeMap.setDefault(DefaultMimeMapFactory.create());
+        MimeMap.setDefaultSupplier(DefaultMimeMapFactory::create);
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/com/android/internal/util/MimeIconUtils.java b/core/java/com/android/internal/util/MimeIconUtils.java
index 2230c31..31ea5b2 100644
--- a/core/java/com/android/internal/util/MimeIconUtils.java
+++ b/core/java/com/android/internal/util/MimeIconUtils.java
@@ -27,7 +27,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.util.Locale;
 import java.util.Objects;
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java b/core/java/com/android/internal/util/function/DecConsumer.java
similarity index 62%
rename from services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
rename to core/java/com/android/internal/util/function/DecConsumer.java
index 93c9ada..0abb785 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
+++ b/core/java/com/android/internal/util/function/DecConsumer.java
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.server.integrity.engine;
+package com.android.internal.util.function;
+
+import java.util.function.Consumer;
 
 /**
- * The engine used to evaluate rules against app installs.
+ * A 10-argument {@link Consumer}
  *
- * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
- * to allow/block that install.
+ * @hide
  */
-public final class RuleEvaluation {
-    private static final String TAG = "RuleEvaluation";
-
-    // TODO: Add singleton injection.
+public interface DecConsumer<A, B, C, D, E, F, G, H, I, J> {
+    void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j);
 }
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java b/core/java/com/android/internal/util/function/DecFunction.java
similarity index 62%
copy from services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
copy to core/java/com/android/internal/util/function/DecFunction.java
index 93c9ada..59fc5e6 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
+++ b/core/java/com/android/internal/util/function/DecFunction.java
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.server.integrity.engine;
+package com.android.internal.util.function;
+
+import java.util.function.Function;
 
 /**
- * The engine used to evaluate rules against app installs.
+ * A 10-argument {@link Function}
  *
- * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
- * to allow/block that install.
+ * @hide
  */
-public final class RuleEvaluation {
-    private static final String TAG = "RuleEvaluation";
-
-    // TODO: Add singleton injection.
+public interface DecFunction<A, B, C, D, E, F, G, H, I, J, R> {
+    R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j);
 }
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java b/core/java/com/android/internal/util/function/DecPredicate.java
similarity index 62%
copy from services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
copy to core/java/com/android/internal/util/function/DecPredicate.java
index 93c9ada..975993d 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
+++ b/core/java/com/android/internal/util/function/DecPredicate.java
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.server.integrity.engine;
+package com.android.internal.util.function;
+
+import java.util.function.Predicate;
 
 /**
- * The engine used to evaluate rules against app installs.
+ * A 10-argument {@link Predicate}
  *
- * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
- * to allow/block that install.
+ * @hide
  */
-public final class RuleEvaluation {
-    private static final String TAG = "RuleEvaluation";
-
-    // TODO: Add singleton injection.
+public interface DecPredicate<A, B, C, D, E, F, G, H, I, J> {
+    boolean test(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j);
 }
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java b/core/java/com/android/internal/util/function/UndecConsumer.java
similarity index 62%
copy from services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
copy to core/java/com/android/internal/util/function/UndecConsumer.java
index 93c9ada..1a1d4ca 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
+++ b/core/java/com/android/internal/util/function/UndecConsumer.java
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.server.integrity.engine;
+package com.android.internal.util.function;
+
+import java.util.function.Consumer;
 
 /**
- * The engine used to evaluate rules against app installs.
+ * A 11-argument {@link Consumer}
  *
- * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
- * to allow/block that install.
+ * @hide
  */
-public final class RuleEvaluation {
-    private static final String TAG = "RuleEvaluation";
-
-    // TODO: Add singleton injection.
+public interface UndecConsumer<A, B, C, D, E, F, G, H, I, J, K> {
+    void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
 }
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java b/core/java/com/android/internal/util/function/UndecFunction.java
similarity index 62%
copy from services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
copy to core/java/com/android/internal/util/function/UndecFunction.java
index 93c9ada..5cd324c 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
+++ b/core/java/com/android/internal/util/function/UndecFunction.java
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.server.integrity.engine;
+package com.android.internal.util.function;
+
+import java.util.function.Function;
 
 /**
- * The engine used to evaluate rules against app installs.
+ * A 11-argument {@link Function}
  *
- * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
- * to allow/block that install.
+ * @hide
  */
-public final class RuleEvaluation {
-    private static final String TAG = "RuleEvaluation";
-
-    // TODO: Add singleton injection.
+public interface UndecFunction<A, B, C, D, E, F, G, H, I, J, K, R> {
+    R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
 }
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java b/core/java/com/android/internal/util/function/UndecPredicate.java
similarity index 62%
copy from services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
copy to core/java/com/android/internal/util/function/UndecPredicate.java
index 93c9ada..c09193e 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluation.java
+++ b/core/java/com/android/internal/util/function/UndecPredicate.java
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.server.integrity.engine;
+package com.android.internal.util.function;
+
+import java.util.function.Predicate;
 
 /**
- * The engine used to evaluate rules against app installs.
+ * A 11-argument {@link Predicate}
  *
- * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
- * to allow/block that install.
+ * @hide
  */
-public final class RuleEvaluation {
-    private static final String TAG = "RuleEvaluation";
-
-    // TODO: Add singleton injection.
+public interface UndecPredicate<A, B, C, D, E, F, G, H, I, J, K> {
+    boolean test(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
 }
diff --git a/core/java/com/android/internal/util/function/pooled/OmniFunction.java b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
index d74e715..7a17253 100755
--- a/core/java/com/android/internal/util/function/pooled/OmniFunction.java
+++ b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
@@ -18,6 +18,8 @@
 
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
+import com.android.internal.util.function.DecConsumer;
+import com.android.internal.util.function.DecFunction;
 import com.android.internal.util.function.HeptConsumer;
 import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HexConsumer;
@@ -32,6 +34,8 @@
 import com.android.internal.util.function.QuintFunction;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.TriFunction;
+import com.android.internal.util.function.UndecConsumer;
+import com.android.internal.util.function.UndecFunction;
 
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
@@ -43,62 +47,65 @@
  *
  * @hide
  */
-abstract class OmniFunction<A, B, C, D, E, F, G, H, I, R> implements
+abstract class OmniFunction<A, B, C, D, E, F, G, H, I, J, K, R> implements
         PooledFunction<A, R>, BiFunction<A, B, R>, TriFunction<A, B, C, R>,
         QuadFunction<A, B, C, D, R>, QuintFunction<A, B, C, D, E, R>,
         HexFunction<A, B, C, D, E, F, R>, HeptFunction<A, B, C, D, E, F, G, R>,
         OctFunction<A, B, C, D, E, F, G, H, R>, NonaFunction<A, B, C, D, E, F, G, H, I, R>,
+        DecFunction<A, B, C, D, E, F, G, H, I, J, R>,
+        UndecFunction<A, B, C, D, E, F, G, H, I, J, K, R>,
         PooledConsumer<A>, BiConsumer<A, B>, TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>,
         QuintConsumer<A, B, C, D, E>, HexConsumer<A, B, C, D, E, F>,
         HeptConsumer<A, B, C, D, E, F, G>, OctConsumer<A, B, C, D, E, F, G, H>,
-        NonaConsumer<A, B, C, D, E, F, G, H, I>, PooledPredicate<A>, BiPredicate<A, B>,
-        PooledSupplier<R>, PooledRunnable, ThrowingRunnable, ThrowingSupplier<R>,
-        PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
+        NonaConsumer<A, B, C, D, E, F, G, H, I>, DecConsumer<A, B, C, D, E, F, G, H, I, J>,
+        UndecConsumer<A, B, C, D, E, F, G, H, I, J, K>,
+        PooledPredicate<A>, BiPredicate<A, B>, PooledSupplier<R>, PooledRunnable, ThrowingRunnable,
+        ThrowingSupplier<R>, PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
 
-    abstract R invoke(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+    abstract R invoke(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
 
     @Override
     public R apply(A o, B o2) {
-        return invoke(o, o2, null, null, null, null, null, null, null);
+        return invoke(o, o2, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A o) {
-        return invoke(o, null, null, null, null, null, null, null, null);
+        return invoke(o, null, null, null, null, null, null, null, null, null, null);
     }
 
-    public abstract <V> OmniFunction<A, B, C, D, E, F, G, H, I, V> andThen(
+    public abstract <V> OmniFunction<A, B, C, D, E, F, G, H, I, J, K, V> andThen(
             Function<? super R, ? extends V> after);
-    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> negate();
+    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, J, K, R> negate();
 
     @Override
     public void accept(A o, B o2) {
-        invoke(o, o2, null, null, null, null, null, null, null);
+        invoke(o, o2, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A o) {
-        invoke(o, null, null, null, null, null, null, null, null);
+        invoke(o, null, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public void run() {
-        invoke(null, null, null, null, null, null, null, null, null);
+        invoke(null, null, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public R get() {
-        return invoke(null, null, null, null, null, null, null, null, null);
+        return invoke(null, null, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public boolean test(A o, B o2) {
-        return (Boolean) invoke(o, o2, null, null, null, null, null, null, null);
+        return (Boolean) invoke(o, o2, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public boolean test(A o) {
-        return (Boolean) invoke(o, null, null, null, null, null, null, null, null);
+        return (Boolean) invoke(o, null, null, null, null, null, null, null, null, null, null);
     }
 
     @Override
@@ -113,72 +120,92 @@
 
     @Override
     public R apply(A a, B b, C c) {
-        return invoke(a, b, c, null, null, null, null, null, null);
+        return invoke(a, b, c, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c) {
-        invoke(a, b, c, null, null, null, null, null, null);
+        invoke(a, b, c, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d) {
-        return invoke(a, b, c, d, null, null, null, null, null);
+        return invoke(a, b, c, d, null, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e) {
-        return invoke(a, b, c, d, e, null, null, null, null);
+        return invoke(a, b, c, d, e, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f) {
-        return invoke(a, b, c, d, e, f, null, null, null);
+        return invoke(a, b, c, d, e, f, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f, G g) {
-        return invoke(a, b, c, d, e, f, g, null, null);
+        return invoke(a, b, c, d, e, f, g, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f, G g, H h) {
-        return invoke(a, b, c, d, e, f, g, h, null);
+        return invoke(a, b, c, d, e, f, g, h, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
-        return invoke(a, b, c, d, e, f, g, h, i);
+        return invoke(a, b, c, d, e, f, g, h, i, null, null);
+    }
+
+    @Override
+    public R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) {
+        return invoke(a, b, c, d, e, f, g, h, i, j, null);
+    }
+
+    @Override
+    public R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) {
+        return invoke(a, b, c, d, e, f, g, h, i, j, k);
     }
 
     @Override
     public void accept(A a, B b, C c, D d) {
-        invoke(a, b, c, d, null, null, null, null, null);
+        invoke(a, b, c, d, null, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e) {
-        invoke(a, b, c, d, e, null, null, null, null);
+        invoke(a, b, c, d, e, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f) {
-        invoke(a, b, c, d, e, f, null, null, null);
+        invoke(a, b, c, d, e, f, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f, G g) {
-        invoke(a, b, c, d, e, f, g, null, null);
+        invoke(a, b, c, d, e, f, g, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f, G g, H h) {
-        invoke(a, b, c, d, e, f, g, h, null);
+        invoke(a, b, c, d, e, f, g, h, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
-        invoke(a, b, c, d, e, f, g, h, i);
+        invoke(a, b, c, d, e, f, g, h, i, null, null);
+    }
+
+    @Override
+    public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) {
+        invoke(a, b, c, d, e, f, g, h, i, j, null);
+    }
+
+    @Override
+    public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) {
+        invoke(a, b, c, d, e, f, g, h, i, j, k);
     }
 
     @Override
@@ -192,5 +219,5 @@
     }
 
     @Override
-    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> recycleOnUse();
+    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, J, K, R> recycleOnUse();
 }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index c00932e..b9bf933 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -21,6 +21,8 @@
 
 import android.os.Message;
 
+import com.android.internal.util.function.DecConsumer;
+import com.android.internal.util.function.DecFunction;
 import com.android.internal.util.function.HeptConsumer;
 import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HexConsumer;
@@ -35,6 +37,8 @@
 import com.android.internal.util.function.QuintFunction;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.TriFunction;
+import com.android.internal.util.function.UndecConsumer;
+import com.android.internal.util.function.UndecFunction;
 import com.android.internal.util.function.pooled.PooledLambdaImpl.LambdaType.ReturnType;
 
 import java.util.function.BiConsumer;
@@ -181,7 +185,7 @@
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -198,7 +202,7 @@
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -215,7 +219,7 @@
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -246,7 +250,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -266,7 +270,7 @@
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -284,7 +288,7 @@
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -302,7 +306,7 @@
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -320,7 +324,7 @@
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -338,7 +342,7 @@
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -356,7 +360,7 @@
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -374,7 +378,7 @@
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -392,7 +396,7 @@
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -410,7 +414,7 @@
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -442,7 +446,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -463,7 +467,7 @@
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -482,7 +486,7 @@
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -501,7 +505,7 @@
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -520,7 +524,7 @@
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -539,7 +543,7 @@
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -558,7 +562,7 @@
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -577,7 +581,7 @@
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -596,7 +600,7 @@
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -629,7 +633,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -651,7 +655,7 @@
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -671,7 +675,7 @@
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -691,7 +695,7 @@
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -711,7 +715,7 @@
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -731,7 +735,7 @@
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -751,7 +755,7 @@
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -771,7 +775,7 @@
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -791,7 +795,7 @@
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -811,7 +815,7 @@
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -831,7 +835,7 @@
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -865,7 +869,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -888,7 +892,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -909,7 +913,7 @@
                     function, A arg1, B arg2, C arg3, D arg4, E arg5) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -945,7 +949,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -969,7 +973,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -991,7 +995,7 @@
                     ? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1028,7 +1032,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -1053,7 +1057,7 @@
                     ? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1077,7 +1081,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1115,7 +1119,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -1142,7 +1146,7 @@
             H arg8) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1167,7 +1171,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 8, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                null);
+                null, null, null);
     }
 
     /**
@@ -1207,7 +1211,7 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                    null);
+                    null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -1235,7 +1239,7 @@
             E arg5, F arg6, G arg7, H arg8, I arg9) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                arg9);
+                arg9, null, null);
     }
 
     /**
@@ -1261,7 +1265,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9) {
         return acquire(PooledLambdaImpl.sPool,
                 function, 9, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                arg9);
+                arg9, null, null);
     }
 
     /**
@@ -1302,7 +1306,209 @@
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                     function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
-                    arg9);
+                    arg9, null, null);
+            return Message.obtain().setCallback(callback.recycleOnUse());
+        }
+    }
+
+    /**
+     * {@link PooledRunnable} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @return a {@link PooledRunnable}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) }
+     */
+    static <A, B, C, D, E, F, G, H, I, J> PooledRunnable obtainRunnable(
+            DecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J> function, A arg1, B arg2, C arg3,
+            D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 10, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9, arg10, null);
+    }
+
+    /**
+     * {@link PooledSupplier} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @return a {@link PooledSupplier}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) }
+     */
+    static <A, B, C, D, E, F, G, H, I, J, R> PooledSupplier<R> obtainSupplier(
+            DecFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                                ? super G, ? super H, ? super I, ? super J, ? extends R> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 10, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9, arg10, null);
+    }
+
+    /**
+     * Factory of {@link Message}s that contain an
+     * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+     * {@link Message#getCallback internal callback}.
+     *
+     * The callback is equivalent to one obtainable via
+     * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+     *
+     * Note that using this method with {@link android.os.Handler#handleMessage}
+     * is more efficient than the alternative of {@link android.os.Handler#post}
+     * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+     * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+     *
+     * You may optionally set a {@link Message#what} for the message if you want to be
+     * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+     * there's no need to do so
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+     * arg7, arg8, arg9, arg10) } when handled
+     */
+    static <A, B, C, D, E, F, G, H, I, J> Message obtainMessage(
+            DecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J> function, A arg1, B arg2, C arg3,
+            D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) {
+        synchronized (Message.sPoolSync) {
+            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+                    function, 10, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
+                    arg8, arg9, arg10, null);
+            return Message.obtain().setCallback(callback.recycleOnUse());
+        }
+    }
+
+    /**
+     * {@link PooledRunnable} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @param arg11 parameter supplied to {@code function} on call
+     * @return a {@link PooledRunnable}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
+     *         arg11) }
+     */
+    static <A, B, C, D, E, F, G, H, I, J, K> PooledRunnable obtainRunnable(
+            UndecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J, ? super K> function, A arg1, B arg2,
+            C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10, K arg11) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 11, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9, arg10, arg11);
+    }
+
+    /**
+     * {@link PooledSupplier} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @param arg11 parameter supplied to {@code function} on call
+     * @return a {@link PooledSupplier}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
+     *         arg11) }
+     */
+    static <A, B, C, D, E, F, G, H, I, J, K, R> PooledSupplier<R> obtainSupplier(
+            UndecFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J, ? super K, ? extends R> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10,
+            K arg11) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 11, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9, arg10, arg11);
+    }
+
+    /**
+     * Factory of {@link Message}s that contain an
+     * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+     * {@link Message#getCallback internal callback}.
+     *
+     * The callback is equivalent to one obtainable via
+     * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+     *
+     * Note that using this method with {@link android.os.Handler#handleMessage}
+     * is more efficient than the alternative of {@link android.os.Handler#post}
+     * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+     * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+     *
+     * You may optionally set a {@link Message#what} for the message if you want to be
+     * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+     * there's no need to do so
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @param arg10 parameter supplied to {@code function} on call
+     * @param arg11 parameter supplied to {@code function} on call
+     * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+     * arg7, arg8, arg9, arg10, arg11) } when handled
+     */
+    static <A, B, C, D, E, F, G, H, I, J, K> Message obtainMessage(
+            UndecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I, ? super J, ? super K> function, A arg1, B arg2,
+            C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10, K arg11) {
+        synchronized (Message.sPoolSync) {
+            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+                    function, 11, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
+                    arg8, arg9, arg10, arg11);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index e12c031..c7502ef 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -26,6 +26,9 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.DecConsumer;
+import com.android.internal.util.function.DecFunction;
+import com.android.internal.util.function.DecPredicate;
 import com.android.internal.util.function.HeptConsumer;
 import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HeptPredicate;
@@ -47,6 +50,9 @@
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.TriFunction;
 import com.android.internal.util.function.TriPredicate;
+import com.android.internal.util.function.UndecConsumer;
+import com.android.internal.util.function.UndecFunction;
+import com.android.internal.util.function.UndecPredicate;
 
 import java.util.Arrays;
 import java.util.Objects;
@@ -63,12 +69,12 @@
  * @hide
  */
 final class PooledLambdaImpl<R> extends OmniFunction<Object,
-        Object, Object, Object, Object, Object, Object, Object, Object, R> {
+        Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, R> {
 
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "PooledLambdaImpl";
 
-    private static final int MAX_ARGS = 9;
+    private static final int MAX_ARGS = 11;
 
     private static final int MAX_POOL_SIZE = 50;
 
@@ -134,7 +140,7 @@
 
     /**
      * Bit schema:
-     * AAAAAAAAABCDEEEEEEFFFFFF
+     * AAAAAAAAAAABCDEEEEEEFFFFFF
      *
      * Where:
      * A - whether {@link #mArgs arg} at corresponding index was specified at
@@ -171,18 +177,18 @@
 
     @Override
     R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7,
-            Object a8, Object a9) {
+            Object a8, Object a9, Object a10, Object a11) {
         checkNotRecycled();
         if (DEBUG) {
             Log.i(LOG_TAG, this + ".invoke("
                     + commaSeparateFirstN(
-                            new Object[] { a1, a2, a3, a4, a5, a6, a7, a8, a9 },
+                            new Object[] { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 },
                             LambdaType.decodeArgCount(getFlags(MASK_EXPOSED_AS)))
                     + ")");
         }
         final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3) && fillInArg(a4)
                 && fillInArg(a5) && fillInArg(a6) && fillInArg(a7) && fillInArg(a8)
-                && fillInArg(a9);
+                && fillInArg(a9) && fillInArg(a10) && fillInArg(a11);
         int argCount = LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE));
         if (argCount != LambdaType.MASK_ARG_COUNT) {
             for (int i = 0; i < argCount; i++) {
@@ -410,6 +416,48 @@
                     }
                 }
             } break;
+
+            case 10: {
+                switch (returnType) {
+                    case LambdaType.ReturnType.VOID: {
+                        ((DecConsumer) mFunc).accept(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8), popArg(9));
+                        return null;
+                    }
+                    case LambdaType.ReturnType.BOOLEAN: {
+                        return (R) (Object) ((DecPredicate) mFunc).test(popArg(0),
+                                popArg(1), popArg(2), popArg(3), popArg(4),
+                                popArg(5), popArg(6), popArg(7), popArg(8), popArg(9));
+                    }
+                    case LambdaType.ReturnType.OBJECT: {
+                        return (R) ((DecFunction) mFunc).apply(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8), popArg(9));
+                    }
+                }
+            } break;
+
+            case 11: {
+                switch (returnType) {
+                    case LambdaType.ReturnType.VOID: {
+                        ((UndecConsumer) mFunc).accept(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8), popArg(9), popArg(10));
+                        return null;
+                    }
+                    case LambdaType.ReturnType.BOOLEAN: {
+                        return (R) (Object) ((UndecPredicate) mFunc).test(popArg(0),
+                                popArg(1), popArg(2), popArg(3), popArg(4),
+                                popArg(5), popArg(6), popArg(7), popArg(8), popArg(9), popArg(10));
+                    }
+                    case LambdaType.ReturnType.OBJECT: {
+                        return (R) ((UndecFunction) mFunc).apply(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8), popArg(9), popArg(10));
+                    }
+                }
+            } break;
         }
         throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
     }
@@ -475,7 +523,7 @@
      */
     static <E extends PooledLambda> E acquire(Pool pool, Object func,
             int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c,
-            Object d, Object e, Object f, Object g, Object h, Object i) {
+            Object d, Object e, Object f, Object g, Object h, Object i, Object j, Object k) {
         PooledLambdaImpl r = acquire(pool);
         if (DEBUG) {
             Log.i(LOG_TAG,
@@ -493,6 +541,8 @@
                             + ", g = " + g
                             + ", h = " + h
                             + ", i = " + i
+                            + ", j = " + j
+                            + ", k = " + k
                             + ")");
         }
         r.mFunc = Preconditions.checkNotNull(func);
@@ -508,6 +558,8 @@
         setIfInBounds(r.mArgs, 6, g);
         setIfInBounds(r.mArgs, 7, h);
         setIfInBounds(r.mArgs, 8, i);
+        setIfInBounds(r.mArgs, 9, j);
+        setIfInBounds(r.mArgs, 10, k);
         return (E) r;
     }
 
@@ -564,13 +616,13 @@
 
     @Override
     public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
-            R> negate() {
+            Object, Object, R> negate() {
         throw new UnsupportedOperationException();
     }
 
     @Override
     public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
-            V> andThen(Function<? super R, ? extends V> after) {
+            Object, Object, V> andThen(Function<? super R, ? extends V> after) {
         throw new UnsupportedOperationException();
     }
 
@@ -591,7 +643,7 @@
 
     @Override
     public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
-            R> recycleOnUse() {
+            Object, Object, R> recycleOnUse() {
         if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()");
         mFlags |= FLAG_RECYCLE_ON_USE;
         return this;
@@ -683,6 +735,8 @@
                 case 7: return "Hept";
                 case 8: return "Oct";
                 case 9: return "Nona";
+                case 10: return "Dec";
+                case 11: return "Undec";
                 default: return "" + argCount + "arg";
             }
         }
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 8aa6f86..3cefeea 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -191,9 +191,21 @@
     return -1;
 }
 
+static bool verifyGroup(JNIEnv* env, int grp)
+{
+    if (grp < SP_DEFAULT || grp  >= SP_CNT) {
+        signalExceptionForError(env, EINVAL, grp);
+        return false;
+    }
+    return true;
+}
+
 void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint grp)
 {
     ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp);
+    if (!verifyGroup(env, grp)) {
+        return;
+    }
     SchedPolicy sp = (SchedPolicy) grp;
     int res = set_sched_policy(tid, sp);
     if (res != NO_ERROR) {
@@ -204,6 +216,9 @@
 void android_os_Process_setThreadGroupAndCpuset(JNIEnv* env, jobject clazz, int tid, jint grp)
 {
     ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp);
+    if (!verifyGroup(env, grp)) {
+        return;
+    }
     SchedPolicy sp = (SchedPolicy) grp;
     int res = set_sched_policy(tid, sp);
 
@@ -234,6 +249,9 @@
         grp = SP_FOREGROUND;
         isDefault = true;
     }
+    if (!verifyGroup(env, grp)) {
+        return;
+    }
     SchedPolicy sp = (SchedPolicy) grp;
 
     if (kDebugPolicy) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7a0d0cb..7ce370f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -794,6 +794,18 @@
         android:permissionFlags="hardRestricted"
         android:protectionLevel="dangerous" />
 
+    <!-- @SystemApi @TestApi Allows an application to forward cell broadcast messages to the cell
+         broadcast module. This is required in order to bind to the cell broadcast service, and
+         ensures that only the system can forward messages to it.
+
+         <p>Protection level: signature|privileged
+
+         @hide -->
+    <permission android:name="android.permission.BIND_CELL_BROADCAST_SERVICE"
+        android:label="@string/permlab_bindCellBroadcastService"
+        android:description="@string/permdesc_bindCellBroadcastService"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi @TestApi Allows an application to read previously received cell broadcast
          messages and to register a content observer to get notifications when
          a cell broadcast has been received and added to the database. For
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e3337b7..7eca699 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -433,6 +433,10 @@
         -->
     </string-array>
 
+    <!-- Package name for the default CellBroadcastService module [DO NOT TRANSLATE] -->
+    <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastreceiver
+    </string>
+
     <!-- If the mobile hotspot feature requires provisioning, a package name and class name
         can be provided to launch a supported application that provisions the devices.
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b53a399..4e32708 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -890,6 +890,16 @@
       messages. This means the app could monitor or delete messages sent to your
       device without showing them to you.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this.[CHAR LIMIT=NONE] -->
+    <string name="permlab_bindCellBroadcastService">Forward cell broadcast messages</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_bindCellBroadcastService">Allows the app to bind to the
+        cell broadcast module in order to forward cell broadcast messages
+        as they are received. Cell broadcast alerts are delivered in some
+        locations to warn you of emergency situations. Malicious apps may
+        interfere with the performance or operation of your device when an
+        emergency cell broadcast is received.</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_readCellBroadcasts">read cell broadcast messages</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e2f2b2c..a8b5340 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -747,6 +747,7 @@
   <java-symbol type="string" name="config_default_dns_server" />
   <java-symbol type="string" name="config_ethernet_iface_regex" />
   <java-symbol type="array" name="config_ethernet_interfaces" />
+  <java-symbol type="string" name="cellbroadcast_default_package" />
   <java-symbol type="string" name="config_forceVoiceInteractionServicePackage" />
   <java-symbol type="string" name="config_mms_user_agent" />
   <java-symbol type="string" name="config_mms_user_agent_profile_url" />
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
index d3bf0dd..e9d5bb1 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -20,7 +20,6 @@
         "android.test.base",
     ],
     static_libs: ["androidx.test.rules", "truth-prebuilt"],
-    test_suites: ["general-tests"],
     sdk_version: "test_current",
     platform_apis: true,
 }
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 89523d6..51136b9 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -127,6 +127,7 @@
         <permission name="android.permission.ACCESS_IMS_CALL_SERVICE"/>
         <permission name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"/>
         <permission name="android.permission.BIND_CARRIER_SERVICES"/>
+        <permission name="android.permission.BIND_CELL_BROADCAST_SERVICE"/>
         <permission name="android.permission.BIND_IMS_SERVICE"/>
         <permission name="android.permission.BIND_TELEPHONY_DATA_SERVICE"/>
         <permission name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"/>
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 1b713b6..81213b9 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -40,6 +40,7 @@
     void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit);
     void requestSetVolume(IMediaRouterClient client, String routeId, int volume);
     void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction);
+    void setControlCategories(IMediaRouterClient client, in List<String> categories);
 
     // Methods for media router 2
     void registerClient2(IMediaRouter2Client client, String packageName);
@@ -52,7 +53,7 @@
      * @param route the route to be selected
      */
     void selectRoute2(IMediaRouter2Client client, in @nullable MediaRoute2Info route);
-    void setControlCategories(IMediaRouter2Client client, in List<String> categories);
+    void setControlCategories2(IMediaRouter2Client client, in List<String> categories);
 
     void registerManager(IMediaRouter2Manager manager, String packageName);
     void unregisterManager(IMediaRouter2Manager manager);
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 8887c7c..09221a37 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -23,7 +23,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.mtp.MtpConstants;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.util.HashMap;
 
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d72231f..9cb7869 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -49,6 +49,8 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Objects;
@@ -82,6 +84,7 @@
 
         final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
         final ArrayList<RouteCategory> mCategories = new ArrayList<RouteCategory>();
+        List<String> mControlCategories = Collections.emptyList();
 
         final RouteCategory mSystemCategory;
 
@@ -358,6 +361,18 @@
             return mDisplayService.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
         }
 
+        public void setControlCategories(Collection<String> controlCategories) {
+            List<String> newControlCategories = new ArrayList<>(controlCategories);
+            mControlCategories = newControlCategories;
+            if (mClient != null) {
+                try {
+                    mMediaRouterService.setControlCategories(mClient, newControlCategories);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Unable to set control categories.", ex);
+                }
+            }
+        }
+
         private void updatePresentationDisplays(int changedDisplayId) {
             final int count = mRoutes.size();
             for (int i = 0; i < count; i++) {
@@ -406,6 +421,7 @@
                 try {
                     Client client = new Client();
                     mMediaRouterService.registerClientAsUser(client, mPackageName, userId);
+                    mMediaRouterService.setControlCategories(client, mControlCategories);
                     mClient = client;
                 } catch (RemoteException ex) {
                     Log.e(TAG, "Unable to register media router client.", ex);
@@ -1302,6 +1318,19 @@
         sStatic.rebindAsUser(userId);
     }
 
+    /**
+     * Sets the control categories of the application.
+     * Routes that support at least one of the given control categories only exists and are handled
+     * by the media router.
+     *
+     * @hide
+     */
+    public void setControlCategories(@NonNull Collection<String> controlCategories) {
+        Objects.requireNonNull(controlCategories, "control categories must not be null");
+
+        sStatic.setControlCategories(controlCategories);
+    }
+
     static void updateRoute(final RouteInfo info) {
         dispatchRouteChanged(info);
     }
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 8e29e34..ed35ef6 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -129,7 +129,7 @@
                 Client client = new Client();
                 try {
                     mMediaRouterService.registerClient2(client, mPackageName);
-                    mMediaRouterService.setControlCategories(client, mControlCategories);
+                    mMediaRouterService.setControlCategories2(client, mControlCategories);
                     mClient = client;
                 } catch (RemoteException ex) {
                     Log.e(TAG, "Unable to register media router.", ex);
@@ -188,7 +188,7 @@
         }
         if (client != null) {
             try {
-                mMediaRouterService.setControlCategories(client, newControlCategories);
+                mMediaRouterService.setControlCategories2(client, newControlCategories);
             } catch (RemoteException ex) {
                 Log.e(TAG, "Unable to set control categories.", ex);
             }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
index 38f0175..481f479 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
@@ -31,7 +31,7 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 3abf0a4..a3ed07a 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -27,6 +27,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.media.MediaRoute2Info;
+import android.media.MediaRouter;
 import android.media.MediaRouter2;
 import android.media.MediaRouter2Manager;
 import android.support.test.InstrumentationRegistry;
@@ -72,7 +73,8 @@
 
     private Context mContext;
     private MediaRouter2Manager mManager;
-    private MediaRouter2 mRouter;
+    private MediaRouter mRouter;
+    private MediaRouter2 mRouter2;
     private Executor mExecutor;
     private String mPackageName;
 
@@ -89,7 +91,8 @@
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getTargetContext();
         mManager = MediaRouter2Manager.getInstance(mContext);
-        mRouter = MediaRouter2.getInstance(mContext);
+        mRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+        mRouter2 = MediaRouter2.getInstance(mContext);
         //TODO: If we need to support thread pool executors, change this to thread pool executor.
         mExecutor = Executors.newSingleThreadExecutor();
         mPackageName = mContext.getPackageName();
@@ -131,12 +134,12 @@
 
         //TODO: Figure out a more proper way to test.
         // (Control requests shouldn't be used in this way.)
-        mRouter.setControlCategories(CONTROL_CATEGORIES_ALL);
-        mRouter.registerCallback(mExecutor, mockRouterCallback);
-        mRouter.sendControlRequest(
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
+        mRouter2.registerCallback(mExecutor, mockRouterCallback);
+        mRouter2.sendControlRequest(
                 new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2).build(),
                 new Intent(ACTION_REMOVE_ROUTE));
-        mRouter.unregisterCallback(mockRouterCallback);
+        mRouter2.unregisterCallback(mockRouterCallback);
 
         verify(mockCallback, timeout(TIMEOUT_MS)).onRouteRemoved(argThat(
                 (MediaRoute2Info info) ->
@@ -148,15 +151,41 @@
      * Tests if we get proper routes for application that has special control category.
      */
     @Test
+    public void testControlCategoryWithMediaRouter() throws Exception {
+        MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
+        mManager.registerCallback(mExecutor, mockCallback);
+
+        MediaRouter.Callback mockRouterCallback = mock(MediaRouter.Callback.class);
+
+        mRouter.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
+        mRouter.addCallback(MediaRouter.ROUTE_TYPE_USER, mockRouterCallback);
+
+        verify(mockCallback, timeout(TIMEOUT_MS))
+                .onRoutesChanged(argThat(routes -> routes.size() > 0));
+
+        Map<String, MediaRoute2Info> routes =
+                createRouteMap(mManager.getAvailableRoutes(mPackageName));
+
+        Assert.assertEquals(1, routes.size());
+        Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
+
+        mRouter.removeCallback(mockRouterCallback);
+        mManager.unregisterCallback(mockCallback);
+    }
+
+    /**
+     * Tests if we get proper routes for application that has special control category.
+     */
+    @Test
     public void testControlCategory() throws Exception {
         MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
         mManager.registerCallback(mExecutor, mockCallback);
 
         MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
 
-        mRouter.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
-        mRouter.registerCallback(mExecutor, mockRouterCallback);
-        mRouter.unregisterCallback(mockRouterCallback);
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
+        mRouter2.registerCallback(mExecutor, mockRouterCallback);
+        mRouter2.unregisterCallback(mockRouterCallback);
 
         verify(mockCallback, timeout(TIMEOUT_MS))
                 .onRoutesChanged(argThat(routes -> routes.size() > 0));
@@ -177,15 +206,15 @@
     public void testGetRoutes() throws Exception {
         MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
 
-        mRouter.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
-        mRouter.registerCallback(mExecutor, mockCallback);
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
+        mRouter2.registerCallback(mExecutor, mockCallback);
         verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
                 .onRoutesChanged(argThat(routes -> routes.size() > 0));
-        Map<String, MediaRoute2Info> routes = createRouteMap(mRouter.getRoutes());
+        Map<String, MediaRoute2Info> routes = createRouteMap(mRouter2.getRoutes());
         Assert.assertEquals(1, routes.size());
         Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
 
-        mRouter.unregisterCallback(mockCallback);
+        mRouter2.unregisterCallback(mockCallback);
     }
 
     @Test
@@ -194,8 +223,8 @@
         MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class);
 
         mManager.registerCallback(mExecutor, managerCallback);
-        mRouter.setControlCategories(CONTROL_CATEGORIES_ALL);
-        mRouter.registerCallback(mExecutor, mockRouterCallback);
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
+        mRouter2.registerCallback(mExecutor, mockRouterCallback);
 
         verify(managerCallback, timeout(TIMEOUT_MS))
                 .onRoutesChanged(argThat(routes -> routes.size() > 0));
@@ -211,7 +240,7 @@
                 .onRouteAdded(argThat(route -> route.equals(routeToSelect)));
 
         mManager.unregisterCallback(managerCallback);
-        mRouter.unregisterCallback(mockRouterCallback);
+        mRouter2.unregisterCallback(mockRouterCallback);
     }
 
     /**
@@ -223,8 +252,8 @@
         MediaRouter2.Callback routerCallback = mock(MediaRouter2.Callback.class);
 
         mManager.registerCallback(mExecutor, managerCallback);
-        mRouter.setControlCategories(CONTROL_CATEGORIES_ALL);
-        mRouter.registerCallback(mExecutor, routerCallback);
+        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
+        mRouter2.registerCallback(mExecutor, routerCallback);
 
         verify(managerCallback, timeout(TIMEOUT_MS))
                 .onRoutesChanged(argThat(routes -> routes.size() > 0));
@@ -248,7 +277,7 @@
                 .onRouteChanged(argThat(routeInfo -> TextUtils.equals(ROUTE_ID2, routeInfo.getId())
                         && TextUtils.equals(routeInfo.getClientPackageName(), null)));
 
-        mRouter.unregisterCallback(routerCallback);
+        mRouter2.unregisterCallback(routerCallback);
         mManager.unregisterCallback(managerCallback);
     }
 
diff --git a/mime/java/android/content/type/DefaultMimeMapFactory.java b/mime/java/android/content/type/DefaultMimeMapFactory.java
index 13039a4..03b685d 100644
--- a/mime/java/android/content/type/DefaultMimeMapFactory.java
+++ b/mime/java/android/content/type/DefaultMimeMapFactory.java
@@ -16,7 +16,7 @@
 
 package android.content.type;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 import java.io.BufferedReader;
 import java.io.IOException;
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 9a063aa..5ec1bae 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -29,6 +29,7 @@
 import com.android.systemui.power.EnhancedEstimatesImpl;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
+import com.android.systemui.statusbar.car.CarStatusBar;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
@@ -42,6 +43,8 @@
 import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
 
 @Module
 abstract class CarSystemUIModule {
@@ -94,4 +97,9 @@
     @Binds
     abstract SystemUIRootComponent bindSystemUIRootComponent(
             CarSystemUIRootComponent systemUIRootComponent);
+
+    @Binds
+    @IntoMap
+    @ClassKey(StatusBar.class)
+    public abstract SystemUI providesStatusBar(CarStatusBar statusBar);
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index b0ab5b4..d21f09c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.car;
 
+import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -34,6 +36,7 @@
 import android.graphics.drawable.Drawable;
 import android.inputmethodservice.InputMethodService;
 import android.os.IBinder;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Display;
 import android.view.GestureDetector;
@@ -57,36 +60,83 @@
 import com.android.car.notification.NotificationDataManager;
 import com.android.car.notification.NotificationViewController;
 import com.android.car.notification.PreprocessingManager;
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.RegisterStatusBarResult;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.CarSystemUIFactory;
 import com.android.systemui.Dependency;
+import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SystemUIFactory;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.classifier.FalsingLog;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.doze.DozeLog;
 import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.car.CarQSFragment;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.car.hvac.HvacController;
 import com.android.systemui.statusbar.car.hvac.TemperatureView;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineInitializer;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.InjectionInflationController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Map;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
 /**
  * A status bar (and navigation bar) tailored for the automotive use case.
  */
@@ -175,6 +225,8 @@
     private boolean mHideNavBarForKeyboard;
     private boolean mBottomNavBarVisible;
 
+    private final NavigationBarController mNavigationBarController;
+
     private final CarPowerStateListener mCarPowerStateListener =
             (int state) -> {
                 // When the car powers on, clear all notifications and mute/unread states.
@@ -189,6 +241,116 @@
                 }
             };
 
+    @Inject
+    public CarStatusBar(
+            LightBarController lightBarController,
+            AutoHideController autoHideController,
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            StatusBarIconController statusBarIconController,
+            DozeLog dozeLog,
+            InjectionInflationController injectionInflationController,
+            PulseExpansionHandler pulseExpansionHandler,
+            NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+            KeyguardBypassController keyguardBypassController,
+            KeyguardStateController keyguardStateController,
+            HeadsUpManagerPhone headsUpManagerPhone,
+            DynamicPrivacyController dynamicPrivacyController,
+            BypassHeadsUpNotifier bypassHeadsUpNotifier,
+            @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+            NotifPipelineInitializer notifPipelineInitializer,
+            FalsingManager falsingManager,
+            BroadcastDispatcher broadcastDispatcher,
+            RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+            NotificationGutsManager notificationGutsManager,
+            NotificationLogger notificationLogger,
+            NotificationEntryManager notificationEntryManager,
+            NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+            NotificationViewHierarchyManager notificationViewHierarchyManager,
+            ForegroundServiceController foregroundServiceController,
+            AppOpsController appOpsController,
+            KeyguardViewMediator keyguardViewMediator,
+            ZenModeController zenModeController,
+            NotificationAlertingManager notificationAlertingManager,
+            DisplayMetrics displayMetrics,
+            MetricsLogger metricsLogger,
+            UiOffloadThread uiOffloadThread,
+            NotificationMediaManager notificationMediaManager,
+            NotificationLockscreenUserManager lockScreenUserManager,
+            NotificationRemoteInputManager remoteInputManager,
+            UserSwitcherController userSwitcherController,
+            NetworkController networkController,
+            BatteryController batteryController,
+            SysuiColorExtractor colorExtractor,
+            ScreenLifecycle screenLifecycle,
+            WakefulnessLifecycle wakefulnessLifecycle,
+            SysuiStatusBarStateController statusBarStateController,
+            VibratorHelper vibratorHelper,
+            BubbleController bubbleController,
+            NotificationGroupManager groupManager,
+            NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+            VisualStabilityManager visualStabilityManager,
+            DeviceProvisionedController deviceProvisionedController,
+            NavigationBarController navigationBarController,
+            AssistManager assistManager,
+            NotificationListener notificationListener,
+            ConfigurationController configurationController,
+            StatusBarWindowController statusBarWindowController) {
+        super(
+                lightBarController,
+                autoHideController,
+                keyguardUpdateMonitor,
+                statusBarIconController,
+                dozeLog,
+                injectionInflationController,
+                pulseExpansionHandler,
+                notificationWakeUpCoordinator,
+                keyguardBypassController,
+                keyguardStateController,
+                headsUpManagerPhone,
+                dynamicPrivacyController,
+                bypassHeadsUpNotifier,
+                allowNotificationLongPress,
+                notifPipelineInitializer,
+                falsingManager,
+                broadcastDispatcher,
+                remoteInputQuickSettingsDisabler,
+                notificationGutsManager,
+                notificationLogger,
+                notificationEntryManager,
+                notificationInterruptionStateProvider,
+                notificationViewHierarchyManager,
+                foregroundServiceController,
+                appOpsController,
+                keyguardViewMediator,
+                zenModeController,
+                notificationAlertingManager,
+                displayMetrics,
+                metricsLogger,
+                uiOffloadThread,
+                notificationMediaManager,
+                lockScreenUserManager,
+                remoteInputManager,
+                userSwitcherController,
+                networkController,
+                batteryController,
+                colorExtractor,
+                screenLifecycle,
+                wakefulnessLifecycle,
+                statusBarStateController,
+                vibratorHelper,
+                bubbleController,
+                groupManager,
+                groupAlertTransferHelper,
+                visualStabilityManager,
+                deviceProvisionedController,
+                navigationBarController,
+                assistManager,
+                notificationListener,
+                configurationController,
+                statusBarWindowController);
+        mNavigationBarController = navigationBarController;
+    }
+
     @Override
     public void start() {
         // get the provisioned state before calling the parent class since it's that flow that
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
index ea39317..81ca9ea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
@@ -111,8 +111,9 @@
             for (int op : LOCATION_OPS) {
                 final String permission = AppOpsManager.opToPermission(op);
                 final int permissionFlags = pm.getPermissionFlags(permission, packageName, user);
-                if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName)
-                        == PermissionChecker.PERMISSION_GRANTED) {
+                if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
+                        PermissionChecker.PID_UNKNOWN, uid, packageName)
+                                == PermissionChecker.PERMISSION_GRANTED) {
                     if ((permissionFlags
                             & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0) {
                         showApp = false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
index 60c9984..104cc8f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
@@ -110,9 +110,9 @@
                     final String permission = AppOpsManager.opToPermission(op);
                     final int permissionFlags = pm.getPermissionFlags(permission, packageName,
                             user);
-                    if (PermissionChecker.checkPermission(mContext, permission, -1, uid,
-                            packageName)
-                            == PermissionChecker.PERMISSION_GRANTED) {
+                    if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
+                            PermissionChecker.PID_UNKNOWN, uid, packageName)
+                                    == PermissionChecker.PERMISSION_GRANTED) {
                         if ((permissionFlags
                                 & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)
                                 == 0) {
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index a8ce196..a3d420e 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -104,12 +104,6 @@
 Shows the drag handle for the divider between two apps when in split screen
 mode.
 
-### [com.android.systemui.SystemBars](/packages/SystemUI/src/com/android/systemui/SystemBars.java)
-
-This is a proxy to the actual SystemUI for the status bar. This loads from
-config_statusBarComponent which defaults to StatusBar. (maybe this should be
-removed and copy how config_systemUiVendorServiceComponent works)
-
 ### [com.android.systemui.status.phone.StatusBar](/packages/SystemUI/src/com/android/systemui/status/phone/StatusBar.java)
 
 This shows the UI for the status bar and the notification shade it contains.
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 61210d3..105b27e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -279,7 +279,7 @@
         <item>com.android.systemui.recents.Recents</item>
         <item>com.android.systemui.volume.VolumeUI</item>
         <item>com.android.systemui.stackdivider.Divider</item>
-        <item>com.android.systemui.SystemBars</item>
+        <item>com.android.systemui.statusbar.phone.StatusBar</item>
         <item>com.android.systemui.usb.StorageNotification</item>
         <item>com.android.systemui.power.PowerUI</item>
         <item>com.android.systemui.media.RingtonePlayer</item>
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
index c4dce1e..f9f0f1b 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
@@ -200,6 +200,12 @@
     /**
      */
     @Binds
+    public abstract SysuiStatusBarStateController providesSysuiStatusBarStateController(
+            StatusBarStateControllerImpl statusBarStateControllerImpl);
+
+    /**
+     */
+    @Binds
     public abstract StatusBarIconController provideStatusBarIconController(
             StatusBarIconControllerImpl controllerImpl);
 
@@ -235,10 +241,4 @@
      */
     @Binds
     public abstract FalsingManager provideFalsingmanager(FalsingManagerProxy falsingManagerImpl);
-
-    /**
-     */
-    @Binds
-    public abstract SysuiStatusBarStateController providesSysuiStatusBarStateController(
-            StatusBarStateControllerImpl statusBarStateControllerImpl);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
index 239cbfe..0d24321 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
@@ -40,6 +40,7 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.systemui.plugins.PluginInitializerImpl;
 import com.android.systemui.shared.plugins.PluginManager;
@@ -238,4 +239,10 @@
     public AlarmManager provideAlarmManager(Context context) {
         return context.getSystemService(AlarmManager.class);
     }
+
+    /** */
+    @Provides
+    public LockPatternUtils provideLockPatternUtils(Context context) {
+        return new LockPatternUtils(context);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
deleted file mode 100644
index c4c0fd6..0000000
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui;
-
-import android.util.Log;
-
-import com.android.systemui.statusbar.phone.StatusBar;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Ensure a single status bar service implementation is running at all times, using the in-process
- * implementation according to the product config.
- */
-public class SystemBars extends SystemUI {
-    private static final String TAG = "SystemBars";
-    private static final boolean DEBUG = false;
-    private static final int WAIT_FOR_BARS_TO_DIE = 500;
-
-    // in-process fallback implementation, per the product config
-    private SystemUI mStatusBar;
-
-    @Override
-    public void start() {
-        if (DEBUG) Log.d(TAG, "start");
-        createStatusBarFromConfig();
-    }
-
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mStatusBar != null) {
-            mStatusBar.dump(fd, pw, args);
-        }
-    }
-
-    @Override
-    public void onBootCompleted() {
-        if (mStatusBar != null) {
-            mStatusBar.onBootCompleted();
-        }
-    }
-
-    private void createStatusBarFromConfig() {
-        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
-        final String clsName = mContext.getString(R.string.config_statusBarComponent);
-        if (clsName == null || clsName.length() == 0) {
-            throw andLog("No status bar component configured", null);
-        }
-        Class<?> cls = null;
-        try {
-            cls = mContext.getClassLoader().loadClass(clsName);
-        } catch (Throwable t) {
-            throw andLog("Error loading status bar component: " + clsName, t);
-        }
-        try {
-            mStatusBar = (SystemUI) cls.newInstance();
-        } catch (Throwable t) {
-            throw andLog("Error creating status bar component: " + clsName, t);
-        }
-        mStatusBar.mContext = mContext;
-        mStatusBar.mComponents = mComponents;
-        if (mStatusBar instanceof StatusBar) {
-            SystemUIFactory.getInstance().getRootComponent()
-                    .getStatusBarInjector()
-                    .createStatusBar((StatusBar) mStatusBar);
-        }
-        mStatusBar.start();
-        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
-    }
-
-    private RuntimeException andLog(String msg, Throwable t) {
-        Log.w(TAG, msg, t);
-        throw new RuntimeException(msg, t);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java
index ba2dec0..785038f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java
@@ -44,7 +44,7 @@
     @ClassKey(PowerUI.class)
     public abstract SystemUI bindPowerUI(PowerUI sysui);
 
-    /** Inject into StatusBar. */
+    /** Inject into Recents. */
     @Binds
     @IntoMap
     @ClassKey(Recents.class)
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
index 262b5ec..72831e9 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
@@ -40,6 +40,8 @@
 import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
 
 /**
  * A dagger module for injecting default implementations of components of System UI that may be
@@ -76,6 +78,11 @@
         return SysUiServiceProvider.getComponent(context, StatusBar.class);
     }
 
+    @Binds
+    @IntoMap
+    @ClassKey(StatusBar.class)
+    public abstract SystemUI providesStatusBar(StatusBar statusBar);
+
     @Singleton
     @Provides
     @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
index cb7c998..8105c6a 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
@@ -37,7 +37,7 @@
  *  adb shell setprop debug.falsing_log true
  *
  * The log gets dumped as part of the SystemUI services. To dump on demand:
- *  adb shell dumpsys activity service com.android.systemui SystemBars | grep -A 999 FALSING | less
+ *  adb shell dumpsys activity service com.android.systemui StatusBar | grep -A 999 FALSING | less
  *
  * To dump into logcat:
  *  adb shell setprop debug.falsing_logcat true
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6a7b21a..a8027c0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -234,7 +234,7 @@
      */
     private PowerManager.WakeLock mShowKeyguardWakeLock;
 
-    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     // these are protected by synchronized (this)
 
@@ -317,7 +317,7 @@
      * the keyguard.
      */
     private boolean mWaitingUntilKeyguardVisible = false;
-    private LockPatternUtils mLockPatternUtils;
+    private final LockPatternUtils mLockPatternUtils;
     private boolean mKeyguardDonePending = false;
     private boolean mHideAnimationRun = false;
     private boolean mHideAnimationRunning = false;
@@ -681,10 +681,21 @@
     };
 
     @Inject
-    public KeyguardViewMediator(FalsingManager falsingManager) {
+    public KeyguardViewMediator(
+            Context context,
+            FalsingManager falsingManager,
+            LockPatternUtils lockPatternUtils) {
         super();
 
+        mContext = context;
         mFalsingManager = falsingManager;
+
+        mLockPatternUtils = lockPatternUtils;
+        mStatusBarKeyguardViewManager =
+                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(
+                        mContext,
+                        mViewMediatorCallback,
+                        mLockPatternUtils);
     }
 
     public void userActivity() {
@@ -722,7 +733,6 @@
 
         mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
 
-        mLockPatternUtils = new LockPatternUtils(mContext);
         KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
@@ -736,9 +746,6 @@
             setShowingLocked(false /* showing */, true /* forceCallbacks */);
         }
 
-        mStatusBarKeyguardViewManager =
-                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
-                        mViewMediatorCallback, mLockPatternUtils);
         final ContentResolver cr = mContext.getContentResolver();
 
         mDeviceInteractive = mPM.isInteractive();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index e79f141..da5931a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -347,10 +347,9 @@
     private BrightnessMirrorController mBrightnessMirrorController;
     private boolean mBrightnessMirrorVisible;
     protected BiometricUnlockController mBiometricUnlockController;
-    @Inject LightBarController mLightBarController;
+    private final LightBarController mLightBarController;
     protected LockscreenWallpaper mLockscreenWallpaper;
-    @VisibleForTesting
-    @Inject AutoHideController mAutoHideController;
+    private final AutoHideController mAutoHideController;
 
     private int mNaturalBarHeight = -1;
 
@@ -360,8 +359,7 @@
     protected PhoneStatusBarView mStatusBarView;
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
     protected StatusBarWindowController mStatusBarWindowController;
-    @VisibleForTesting
-    @Inject KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @VisibleForTesting
     DozeServiceHost mDozeServiceHost = new DozeServiceHost();
     private boolean mWakeUpComingFromTouch;
@@ -369,38 +367,21 @@
 
     private final Object mQueueLock = new Object();
 
-    @Inject StatusBarIconController mIconController;
-    @Inject
-    DozeLog mDozeLog;
-    @Inject
-    InjectionInflationController mInjectionInflater;
-    @Inject
-    PulseExpansionHandler mPulseExpansionHandler;
-    @Inject
-    NotificationWakeUpCoordinator mWakeUpCoordinator;
-    @Inject
-    KeyguardBypassController mKeyguardBypassController;
-    @Inject
-    KeyguardStateController mKeyguardStateController;
-    @Inject
-    protected HeadsUpManagerPhone mHeadsUpManager;
-    @Inject
-    DynamicPrivacyController mDynamicPrivacyController;
-    @Inject
-    BypassHeadsUpNotifier mBypassHeadsUpNotifier;
-    @Nullable
-    @Inject
-    protected KeyguardLiftController mKeyguardLiftController;
-    @Inject
-    @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
-    boolean mAllowNotificationLongPress;
-    @Inject
-    protected NotifPipelineInitializer mNotifPipelineInitializer;
-    @Inject
-    protected FalsingManager mFalsingManager;
-
-    @VisibleForTesting
-    @Inject BroadcastDispatcher mBroadcastDispatcher;
+    private final StatusBarIconController mIconController;
+    private final DozeLog mDozeLog;
+    private final InjectionInflationController mInjectionInflater;
+    private final PulseExpansionHandler mPulseExpansionHandler;
+    private final NotificationWakeUpCoordinator mWakeUpCoordinator;
+    private final KeyguardBypassController mKeyguardBypassController;
+    private final KeyguardStateController mKeyguardStateController;
+    private final HeadsUpManagerPhone mHeadsUpManager;
+    private final DynamicPrivacyController mDynamicPrivacyController;
+    private final BypassHeadsUpNotifier mBypassHeadsUpNotifier;
+    private final boolean mAllowNotificationLongPress;
+    private final NotifPipelineInitializer mNotifPipelineInitializer;
+    private final FalsingManager mFalsingManager;
+    private final BroadcastDispatcher mBroadcastDispatcher;
+    private final ConfigurationController mConfigurationController;
 
     // expanded notifications
     protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -413,7 +394,7 @@
     // RemoteInputView to be activated after unlock
     private View mPendingRemoteInputView;
 
-    @Inject RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
+    private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
 
     private View mReportRejectedTouch;
 
@@ -422,17 +403,17 @@
     private final int[] mAbsPos = new int[2];
     private final ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>();
 
-    @Inject NotificationGutsManager mGutsManager;
-    @Inject NotificationLogger mNotificationLogger;
-    @Inject NotificationEntryManager mEntryManager;
+    private final NotificationGutsManager mGutsManager;
+    private final NotificationLogger mNotificationLogger;
+    private final NotificationEntryManager mEntryManager;
     private NotificationListController mNotificationListController;
-    @Inject NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
-    @Inject NotificationViewHierarchyManager mViewHierarchyManager;
-    @Inject ForegroundServiceController mForegroundServiceController;
-    @Inject AppOpsController mAppOpsController;
-    @Inject KeyguardViewMediator mKeyguardViewMediator;
-    @Inject ZenModeController mZenController;
-    @Inject NotificationAlertingManager mNotificationAlertingManager;
+    private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+    private final NotificationViewHierarchyManager mViewHierarchyManager;
+    private final ForegroundServiceController mForegroundServiceController;
+    private final AppOpsController mAppOpsController;
+    private final KeyguardViewMediator mKeyguardViewMediator;
+    private final ZenModeController mZenController;
+    private final NotificationAlertingManager mNotificationAlertingManager;
 
     // for disabling the status bar
     private int mDisabled1 = 0;
@@ -443,7 +424,7 @@
     private final Rect mLastFullscreenStackBounds = new Rect();
     private final Rect mLastDockedStackBounds = new Rect();
 
-    @Inject DisplayMetrics mDisplayMetrics;
+    private final DisplayMetrics mDisplayMetrics;
 
     // XXX: gesture research
     private final GestureRecorder mGestureRec = DEBUG_GESTURES
@@ -452,7 +433,7 @@
 
     private ScreenPinningRequest mScreenPinningRequest;
 
-    @Inject MetricsLogger mMetricsLogger;
+    private final MetricsLogger mMetricsLogger;
 
     // ensure quick settings is disabled until the current user makes it through the setup wizard
     @VisibleForTesting
@@ -489,14 +470,14 @@
     private ViewMediatorCallback mKeyguardViewMediatorCallback;
     protected ScrimController mScrimController;
     protected DozeScrimController mDozeScrimController;
-    @Inject UiOffloadThread mUiOffloadThread;
+    private final UiOffloadThread mUiOffloadThread;
 
     protected boolean mDozing;
     private boolean mDozingRequested;
 
-    @Inject NotificationMediaManager mMediaManager;
-    @Inject NotificationLockscreenUserManager mLockscreenUserManager;
-    @Inject NotificationRemoteInputManager mRemoteInputManager;
+    private final NotificationMediaManager mMediaManager;
+    private final NotificationLockscreenUserManager mLockscreenUserManager;
+    private final NotificationRemoteInputManager mRemoteInputManager;
     private boolean mWallpaperSupported;
 
     private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
@@ -567,18 +548,18 @@
     };
 
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
-    @Inject UserSwitcherController mUserSwitcherController;
-    @Inject NetworkController mNetworkController;
-    @Inject BatteryController mBatteryController;
+    private final UserSwitcherController mUserSwitcherController;
+    private final NetworkController mNetworkController;
+    private final BatteryController mBatteryController;
     protected boolean mPanelExpanded;
     private UiModeManager mUiModeManager;
     protected boolean mIsKeyguard;
     private LogMaker mStatusBarStateLog;
     protected NotificationIconAreaController mNotificationIconAreaController;
     @Nullable private View mAmbientIndicationContainer;
-    @Inject SysuiColorExtractor mColorExtractor;
-    @Inject ScreenLifecycle mScreenLifecycle;
-    @Inject @VisibleForTesting WakefulnessLifecycle mWakefulnessLifecycle;
+    private final SysuiColorExtractor mColorExtractor;
+    private final ScreenLifecycle mScreenLifecycle;
+    private final WakefulnessLifecycle mWakefulnessLifecycle;
 
     private final View.OnClickListener mGoToLockedShadeListener = v -> {
         if (mState == StatusBarState.KEYGUARD) {
@@ -587,7 +568,7 @@
         }
     };
     private boolean mNoAnimationOnNextBarModeChange;
-    @Inject SysuiStatusBarStateController mStatusBarStateController;
+    private final SysuiStatusBarStateController mStatusBarStateController;
 
     private final KeyguardUpdateMonitorCallback mUpdateCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -608,17 +589,13 @@
 
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
     private boolean mVibrateOnOpening;
-    @Inject VibratorHelper mVibratorHelper;
+    private final VibratorHelper mVibratorHelper;
     private ActivityLaunchAnimator mActivityLaunchAnimator;
     protected StatusBarNotificationPresenter mPresenter;
     private NotificationActivityStarter mNotificationActivityStarter;
     private boolean mPulsing;
-    @Inject BubbleController mBubbleController;
-    private final BubbleController.BubbleExpandListener mBubbleExpandListener =
-            (isExpanding, key) -> {
-                mEntryManager.updateNotifications();
-                updateScrimController();
-            };
+    private final BubbleController mBubbleController;
+    private final BubbleController.BubbleExpandListener mBubbleExpandListener;
     private ActivityIntentHelper mActivityIntentHelper;
 
     @Override
@@ -635,6 +612,120 @@
             AppOpsManager.OP_COARSE_LOCATION,
             AppOpsManager.OP_FINE_LOCATION};
 
+    @Inject
+    public StatusBar(
+            LightBarController lightBarController,
+            AutoHideController autoHideController,
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            StatusBarIconController statusBarIconController,
+            DozeLog dozeLog,
+            InjectionInflationController injectionInflationController,
+            PulseExpansionHandler pulseExpansionHandler,
+            NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+            KeyguardBypassController keyguardBypassController,
+            KeyguardStateController keyguardStateController,
+            HeadsUpManagerPhone headsUpManagerPhone,
+            DynamicPrivacyController dynamicPrivacyController,
+            BypassHeadsUpNotifier bypassHeadsUpNotifier,
+            @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+            NotifPipelineInitializer notifPipelineInitializer,
+            FalsingManager falsingManager,
+            BroadcastDispatcher broadcastDispatcher,
+            RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+            NotificationGutsManager notificationGutsManager,
+            NotificationLogger notificationLogger,
+            NotificationEntryManager notificationEntryManager,
+            NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+            NotificationViewHierarchyManager notificationViewHierarchyManager,
+            ForegroundServiceController foregroundServiceController,
+            AppOpsController appOpsController,
+            KeyguardViewMediator keyguardViewMediator,
+            ZenModeController zenModeController,
+            NotificationAlertingManager notificationAlertingManager,
+            DisplayMetrics displayMetrics,
+            MetricsLogger metricsLogger,
+            UiOffloadThread uiOffloadThread,
+            NotificationMediaManager notificationMediaManager,
+            NotificationLockscreenUserManager lockScreenUserManager,
+            NotificationRemoteInputManager remoteInputManager,
+            UserSwitcherController userSwitcherController,
+            NetworkController networkController,
+            BatteryController batteryController,
+            SysuiColorExtractor colorExtractor,
+            ScreenLifecycle screenLifecycle,
+            WakefulnessLifecycle wakefulnessLifecycle,
+            SysuiStatusBarStateController statusBarStateController,
+            VibratorHelper vibratorHelper,
+            BubbleController bubbleController,
+            NotificationGroupManager groupManager,
+            NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+            VisualStabilityManager visualStabilityManager,
+            DeviceProvisionedController deviceProvisionedController,
+            NavigationBarController navigationBarController,
+            AssistManager assistManager,
+            NotificationListener notificationListener,
+            ConfigurationController configurationController,
+            StatusBarWindowController statusBarWindowController) {
+        mLightBarController = lightBarController;
+        mAutoHideController = autoHideController;
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mIconController = statusBarIconController;
+        mDozeLog = dozeLog;
+        mInjectionInflater = injectionInflationController;
+        mPulseExpansionHandler = pulseExpansionHandler;
+        mWakeUpCoordinator = notificationWakeUpCoordinator;
+        mKeyguardBypassController = keyguardBypassController;
+        mKeyguardStateController = keyguardStateController;
+        mHeadsUpManager = headsUpManagerPhone;
+        mDynamicPrivacyController = dynamicPrivacyController;
+        mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
+        mAllowNotificationLongPress = allowNotificationLongPress;
+        mNotifPipelineInitializer = notifPipelineInitializer;
+        mFalsingManager = falsingManager;
+        mBroadcastDispatcher = broadcastDispatcher;
+        mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler;
+        mGutsManager = notificationGutsManager;
+        mNotificationLogger = notificationLogger;
+        mEntryManager = notificationEntryManager;
+        mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+        mViewHierarchyManager = notificationViewHierarchyManager;
+        mForegroundServiceController = foregroundServiceController;
+        mAppOpsController = appOpsController;
+        mKeyguardViewMediator = keyguardViewMediator;
+        mZenController = zenModeController;
+        mNotificationAlertingManager = notificationAlertingManager;
+        mDisplayMetrics = displayMetrics;
+        mMetricsLogger = metricsLogger;
+        mUiOffloadThread = uiOffloadThread;
+        mMediaManager = notificationMediaManager;
+        mLockscreenUserManager = lockScreenUserManager;
+        mRemoteInputManager = remoteInputManager;
+        mUserSwitcherController = userSwitcherController;
+        mNetworkController = networkController;
+        mBatteryController = batteryController;
+        mColorExtractor = colorExtractor;
+        mScreenLifecycle = screenLifecycle;
+        mWakefulnessLifecycle = wakefulnessLifecycle;
+        mStatusBarStateController = statusBarStateController;
+        mVibratorHelper = vibratorHelper;
+        mBubbleController = bubbleController;
+        mGroupManager = groupManager;
+        mGroupAlertTransferHelper = groupAlertTransferHelper;
+        mVisualStabilityManager = visualStabilityManager;
+        mDeviceProvisionedController = deviceProvisionedController;
+        mNavigationBarController = navigationBarController;
+        mAssistManager = assistManager;
+        mNotificationListener = notificationListener;
+        mConfigurationController = configurationController;
+        mStatusBarWindowController = statusBarWindowController;
+
+        mBubbleExpandListener =
+                (isExpanding, key) -> {
+                    mEntryManager.updateNotifications();
+                    updateScrimController();
+                };
+    }
+
     @Override
     public void start() {
         mNotificationListener.registerAsSystemService();
@@ -772,7 +863,7 @@
 
         Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
 
-        Dependency.get(ConfigurationController.class).addCallback(this);
+        mConfigurationController.addCallback(this);
 
         // set the initial view visibility
         Dependency.get(InitController.class).addPostInitTask(this::updateAreThereNotifications);
@@ -805,6 +896,8 @@
         NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
         mNotificationLogger.setUpWithContainer(notifListContainer);
 
+        // TODO: make this injectable. Currently that would create a circular dependency between
+        // NotificationIconAreaController and StatusBar.
         mNotificationIconAreaController = SystemUIFactory.getInstance()
                 .createNotificationIconAreaController(context, this,
                         mWakeUpCoordinator, mKeyguardBypassController,
@@ -869,7 +962,7 @@
                 .commit();
 
         mHeadsUpManager.setUp(mStatusBarWindow, mGroupManager, this, mVisualStabilityManager);
-        Dependency.get(ConfigurationController.class).addCallback(mHeadsUpManager);
+        mConfigurationController.addCallback(mHeadsUpManager);
         mHeadsUpManager.addListener(this);
         mHeadsUpManager.addListener(mNotificationPanel);
         mHeadsUpManager.addListener(mGroupManager);
@@ -1004,11 +1097,10 @@
             });
         }
 
-        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        if (!pm.isScreenOn()) {
+        if (!mPowerManager.isScreenOn()) {
             mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
         }
-        mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+        mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
                 "GestureWakeLock");
         mVibrator = mContext.getSystemService(Vibrator.class);
         int[] pattern = mContext.getResources().getIntArray(
@@ -1131,8 +1223,8 @@
     @Override
     public void wakeUpIfDozing(long time, View where, String why) {
         if (mDozing) {
-            PowerManager pm = mContext.getSystemService(PowerManager.class);
-            pm.wakeUp(time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
+            mPowerManager.wakeUp(
+                    time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
             mWakeUpComingFromTouch = true;
             where.getLocationInWindow(mTmpInt2);
             mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
@@ -1232,13 +1324,12 @@
 
     protected void startKeyguard() {
         Trace.beginSection("StatusBar#startKeyguard");
-        KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
         mBiometricUnlockController = new BiometricUnlockController(mContext,
-                mDozeScrimController, keyguardViewMediator,
+                mDozeScrimController, mKeyguardViewMediator,
                 mScrimController, this, mKeyguardStateController, new Handler(),
                 mKeyguardUpdateMonitor, mKeyguardBypassController);
         putComponent(BiometricUnlockController.class, mBiometricUnlockController);
-        mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
+        mStatusBarKeyguardViewManager = mKeyguardViewMediator.registerStatusBar(this,
                 getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
                 mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller,
                 mKeyguardBypassController);
@@ -1248,7 +1339,7 @@
         mRemoteInputManager.getController().addCallback(mStatusBarKeyguardViewManager);
         mDynamicPrivacyController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
 
-        mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
+        mKeyguardViewMediatorCallback = mKeyguardViewMediator.getViewMediatorCallback();
         mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
         mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
         Dependency.get(KeyguardDismissUtil.class).setDismissHandler(this::executeWhenUnlocked);
@@ -1734,6 +1825,16 @@
         return mPresenter;
     }
 
+    @VisibleForTesting
+    void setBarStateForTest(int state) {
+        mState = state;
+    }
+
+    @VisibleForTesting
+    void setUserSetupForTest(boolean userSetup) {
+        mUserSetup = userSetup;
+    }
+
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
@@ -2425,7 +2526,6 @@
 
     public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
         makeStatusBarView(result);
-        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
     }
 
@@ -2669,7 +2769,6 @@
         }
     }
 
-    // SystemUIService notifies SystemBars of configuration changes, which then calls down here
     @Override
     public void onConfigChanged(Configuration newConfig) {
         updateResources();
@@ -3251,7 +3350,7 @@
         final int themeResId = lockDarkText ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI;
         if (mContext.getThemeResId() != themeResId) {
             mContext.setTheme(themeResId);
-            Dependency.get(ConfigurationController.class).notifyThemeChanged();
+            mConfigurationController.notifyThemeChanged();
         }
     }
 
@@ -3798,8 +3897,7 @@
             return;
         }
         if (!mDeviceInteractive) {
-            PowerManager pm = mContext.getSystemService(PowerManager.class);
-            pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
+            mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
                     "com.android.systemui:CAMERA_GESTURE");
         }
         vibrateForCameraGesture();
@@ -4188,11 +4286,11 @@
     // all notifications
     protected ViewGroup mStackScroller;
 
-    @Inject NotificationGroupManager mGroupManager;
-    @Inject NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
+    private final NotificationGroupManager mGroupManager;
+    private final NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
 
     // handling reordering
-    @Inject VisualStabilityManager mVisualStabilityManager;
+    private final VisualStabilityManager mVisualStabilityManager;
 
     protected AccessibilityManager mAccessibilityManager;
 
@@ -4208,9 +4306,9 @@
     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     protected KeyguardManager mKeyguardManager;
-    @Inject DeviceProvisionedController mDeviceProvisionedController;
+    private final DeviceProvisionedController mDeviceProvisionedController;
 
-    @Inject protected NavigationBarController mNavigationBarController;
+    private final NavigationBarController mNavigationBarController;
 
     // UI-specific methods
 
@@ -4226,7 +4324,7 @@
     protected NotificationShelf mNotificationShelf;
     protected EmptyShadeView mEmptyShadeView;
 
-    @Inject AssistManager mAssistManager;
+    private final AssistManager mAssistManager;
 
     public boolean isDeviceInteractive() {
         return mDeviceInteractive;
@@ -4285,7 +4383,7 @@
         }
     }
 
-    @Inject NotificationListener mNotificationListener;
+    private final NotificationListener mNotificationListener;
 
     public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
         if (snoozeOption.getSnoozeCriterion() != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index cd1f0cc..47b56e0 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -92,7 +92,7 @@
             mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
         } else {
             boolean hasRecordPermission =
-                    PermissionChecker.checkPermission(
+                    PermissionChecker.checkPermissionForPreflight(
                             this, android.Manifest.permission.RECORD_AUDIO, -1, aInfo.uid,
                             mPackageName)
                             == android.content.pm.PackageManager.PERMISSION_GRANTED;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index f163886..1449352 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -65,7 +65,7 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.colorextraction.ColorExtractor;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.logging.testing.FakeMetricsLogger;
 import com.android.internal.statusbar.IStatusBarService;
@@ -89,7 +89,6 @@
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
-import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -100,14 +99,15 @@
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineInitializer;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -122,10 +122,14 @@
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.InjectionInflationController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -144,6 +148,15 @@
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
 public class StatusBarTest extends SysuiTestCase {
+
+    private StatusBar mStatusBar;
+    private FakeMetricsLogger mMetricsLogger;
+    private PowerManager mPowerManager;
+    private TestableNotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+    private CommandQueue mCommandQueue;
+
+    @Mock private LightBarController mLightBarController;
+    @Mock private StatusBarIconController mStatusBarIconController;
     @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     @Mock private KeyguardStateController mKeyguardStateController;
     @Mock private KeyguardIndicationController mKeyguardIndicationController;
@@ -158,7 +171,6 @@
     @Mock private BiometricUnlockController mBiometricUnlockController;
     @Mock private NotificationData mNotificationData;
     @Mock private NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor;
-    @Mock private NotificationViewHierarchyManager mViewHierarchyManager;
     @Mock private VisualStabilityManager mVisualStabilityManager;
     @Mock private NotificationListener mNotificationListener;
     @Mock private KeyguardViewMediator mKeyguardViewMediator;
@@ -185,17 +197,25 @@
     @Mock private NavigationBarController mNavigationBarController;
     @Mock private BypassHeadsUpNotifier mBypassHeadsUpNotifier;
     @Mock private SysuiColorExtractor mColorExtractor;
+    @Mock private ColorExtractor.GradientColors mGradientColors;
     @Mock private DozeLog mDozeLog;
     @Mock private PulseExpansionHandler mPulseExpansionHandler;
-    @Mock private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
     @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
     @Mock private KeyguardBypassController mKeyguardBypassController;
-
-    private TestableStatusBar mStatusBar;
-    private FakeMetricsLogger mMetricsLogger;
-    private PowerManager mPowerManager;
-    private TestableNotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
-    private CommandQueue mCommandQueue;
+    @Mock private InjectionInflationController mInjectionInflationController;
+    @Mock private DynamicPrivacyController mDynamicPrivacyController;
+    @Mock private NotifPipelineInitializer mNotifPipelineInitializer;
+    @Mock private ZenModeController mZenModeController;
+    @Mock private AutoHideController mAutoHideController;
+    @Mock private NotificationViewHierarchyManager mNotificationViewHierarchyManager;
+    @Mock private UserSwitcherController mUserSwitcherController;
+    @Mock private NetworkController mNetworkController;
+    @Mock private VibratorHelper mVibratorHelper;
+    @Mock private BubbleController mBubbleController;
+    @Mock private NotificationGroupManager mGroupManager;
+    @Mock private NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
+    @Mock private StatusBarWindowController mStatusBarWindowController;
+    @Mock private NotificationIconAreaController mNotificationIconAreaController;
 
     @Before
     public void setup() throws Exception {
@@ -249,65 +269,88 @@
                 mHeadsUpManager, mHeadsUpSuppressor);
 
         when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
-        mStatusBar = new TestableStatusBar(
-                mStatusBarKeyguardViewManager,
-                mKeyguardIndicationController,
-                mStackScroller,
-                mPowerManager,
-                mNotificationPanelView,
-                mBarService,
-                mNotificationListener,
-                notificationLogger,
-                mVisualStabilityManager,
-                mViewHierarchyManager,
-                entryManager,
-                mScrimController,
-                mBiometricUnlockController,
-                mKeyguardViewMediator,
-                mRemoteInputManager,
-                mock(NotificationGroupManager.class),
-                mock(NotificationGroupAlertTransferHelper.class),
-                new FalsingManagerFake(),
-                mock(StatusBarWindowController.class),
-                mock(NotificationIconAreaController.class),
-                mDozeScrimController,
-                mock(NotificationShelf.class),
-                mLockscreenUserManager,
-                mCommandQueue,
-                mNotificationPresenter,
-                mock(BubbleController.class),
-                mNavigationBarController,
-                mock(AutoHideController.class),
+
+        WakefulnessLifecycle wakefulnessLifecycle = new WakefulnessLifecycle();
+        wakefulnessLifecycle.dispatchStartedWakingUp();
+        wakefulnessLifecycle.dispatchFinishedWakingUp();
+
+        when(mGradientColors.supportsDarkText()).thenReturn(true);
+        when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+        ConfigurationController configurationController = new ConfigurationControllerImpl(mContext);
+
+        mStatusBar = new StatusBar(
+                mLightBarController,
+                mAutoHideController,
                 mKeyguardUpdateMonitor,
-                mStatusBarWindowView,
-                mBroadcastDispatcher,
-                mAssistManager,
-                mNotificationGutsManager,
-                mNotificationMediaManager,
-                mForegroundServiceController,
-                mAppOpsController,
-                mStatusBarStateController,
-                mDeviceProvisionedController,
-                mNotificationAlertingManager,
-                mNotificationInterruptionStateProvider,
-                mMetricsLogger,
-                mHeadsUpManager,
-                mKeyguardStateController,
-                new ScreenLifecycle(),
-                mBypassHeadsUpNotifier,
-                mColorExtractor,
-                new DisplayMetrics(),
-                Dependency.get(UiOffloadThread.class),
+                mStatusBarIconController,
                 mDozeLog,
+                mInjectionInflationController,
                 mPulseExpansionHandler,
+                mNotificationWakeUpCoordinator,
+                mKeyguardBypassController,
+                mKeyguardStateController,
+                mHeadsUpManager,
+                mDynamicPrivacyController,
+                mBypassHeadsUpNotifier,
+                true,
+                mNotifPipelineInitializer,
+                new FalsingManagerFake(),
+                mBroadcastDispatcher,
                 new RemoteInputQuickSettingsDisabler(
                         mContext,
-                        new ConfigurationControllerImpl(mContext)
+                        configurationController
                 ),
-                mNotificationWakeUpCoordinator,
-                mKeyguardBypassController);
+                mNotificationGutsManager,
+                notificationLogger,
+                entryManager,
+                mNotificationInterruptionStateProvider,
+                mNotificationViewHierarchyManager,
+                mForegroundServiceController,
+                mAppOpsController,
+                mKeyguardViewMediator,
+                mZenModeController,
+                mNotificationAlertingManager,
+                new DisplayMetrics(),
+                mMetricsLogger,
+                Dependency.get(UiOffloadThread.class),
+                mNotificationMediaManager,
+                mLockscreenUserManager,
+                mRemoteInputManager,
+                mUserSwitcherController,
+                mNetworkController,
+                mBatteryController,
+                mColorExtractor,
+                new ScreenLifecycle(),
+                wakefulnessLifecycle,
+                mStatusBarStateController,
+                mVibratorHelper,
+                mBubbleController,
+                mGroupManager,
+                mGroupAlertTransferHelper,
+                mVisualStabilityManager,
+                mDeviceProvisionedController,
+                mNavigationBarController,
+                mAssistManager,
+                mNotificationListener,
+                configurationController,
+                mStatusBarWindowController);
+        // TODO: we should be able to call mStatusBar.start() and have all the below values
+        // initialized automatically.
         mStatusBar.mContext = mContext;
         mStatusBar.mComponents = mContext.getComponents();
+        mStatusBar.mStatusBarKeyguardViewManager = mStatusBarKeyguardViewManager;
+        mStatusBar.mStatusBarWindow = mStatusBarWindowView;
+        mStatusBar.mBiometricUnlockController = mBiometricUnlockController;
+        mStatusBar.mScrimController = mScrimController;
+        mStatusBar.mNotificationPanel = mNotificationPanelView;
+        mStatusBar.mCommandQueue = mCommandQueue;
+        mStatusBar.mDozeScrimController = mDozeScrimController;
+        mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController;
+        mStatusBar.mPresenter = mNotificationPresenter;
+        mStatusBar.mKeyguardIndicationController = mKeyguardIndicationController;
+        mStatusBar.mPowerManager = mPowerManager;
+        mStatusBar.mBarService = mBarService;
+        mStatusBar.mStackScroller = mStackScroller;
         mStatusBar.putComponent(StatusBar.class, mStatusBar);
         Dependency.get(InitController.class).executePostInitTasks();
         entryManager.setUpForTest(mock(NotificationPresenter.class), mStackScroller,
@@ -636,8 +679,8 @@
     @Test
     @RunWithLooper(setAsMainLooper = true)
     public void testUpdateKeyguardState_DoesNotCrash() {
-        mStatusBar.mState = StatusBarState.KEYGUARD;
-        when(mStatusBar.mLockscreenUserManager.getCurrentProfiles()).thenReturn(
+        mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+        when(mLockscreenUserManager.getCurrentProfiles()).thenReturn(
                 new SparseArray<>());
         mStatusBar.onStateChanged(StatusBarState.SHADE);
     }
@@ -768,8 +811,7 @@
         verify(mStatusBarStateController).setState(eq(StatusBarState.KEYGUARD));
 
         // If useFullscreenUserSwitcher is true, state is set to FULLSCREEN_USER_SWITCHER.
-        mStatusBar.mUserSwitcherController = mock(UserSwitcherController.class);
-        when(mStatusBar.mUserSwitcherController.useFullscreenUserSwitcher()).thenReturn(true);
+        when(mUserSwitcherController.useFullscreenUserSwitcher()).thenReturn(true);
         mStatusBar.showKeyguardImpl();
         verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER));
     }
@@ -821,136 +863,6 @@
                 any(UserHandle.class));
     }
 
-    static class TestableStatusBar extends StatusBar {
-        public TestableStatusBar(StatusBarKeyguardViewManager man,
-                KeyguardIndicationController key,
-                NotificationStackScrollLayout stack,
-                PowerManager pm, NotificationPanelView panelView,
-                IStatusBarService barService, NotificationListener notificationListener,
-                NotificationLogger notificationLogger,
-                VisualStabilityManager visualStabilityManager,
-                NotificationViewHierarchyManager viewHierarchyManager,
-                TestableNotificationEntryManager entryManager, ScrimController scrimController,
-                BiometricUnlockController biometricUnlockController,
-                KeyguardViewMediator keyguardViewMediator,
-                NotificationRemoteInputManager notificationRemoteInputManager,
-                NotificationGroupManager notificationGroupManager,
-                NotificationGroupAlertTransferHelper notificationGroupAlertTransferHelper,
-                FalsingManager falsingManager,
-                StatusBarWindowController statusBarWindowController,
-                NotificationIconAreaController notificationIconAreaController,
-                DozeScrimController dozeScrimController,
-                NotificationShelf notificationShelf,
-                NotificationLockscreenUserManager notificationLockscreenUserManager,
-                CommandQueue commandQueue,
-                StatusBarNotificationPresenter notificationPresenter,
-                BubbleController bubbleController,
-                NavigationBarController navBarController,
-                AutoHideController autoHideController,
-                KeyguardUpdateMonitor keyguardUpdateMonitor,
-                StatusBarWindowView statusBarWindow,
-                BroadcastDispatcher broadcastDispatcher,
-                AssistManager assistManager,
-                NotificationGutsManager notificationGutsManager,
-                NotificationMediaManager notificationMediaManager,
-                ForegroundServiceController foregroundServiceController,
-                AppOpsController appOpsController,
-                SysuiStatusBarStateController statusBarStateController,
-                DeviceProvisionedController deviceProvisionedController,
-                NotificationAlertingManager notificationAlertingManager,
-                NotificationInterruptionStateProvider notificationInterruptionStateProvider,
-                MetricsLogger metricsLogger,
-                HeadsUpManagerPhone headsUpManager,
-                KeyguardStateController keyguardStateController,
-                ScreenLifecycle screenLifecycle,
-                BypassHeadsUpNotifier bypassHeadsUpNotifier,
-                SysuiColorExtractor colorExtractor, DisplayMetrics displayMetrics,
-                UiOffloadThread uiOffloadThread,
-                DozeLog dozeLog,
-                PulseExpansionHandler pulseExpansionHandler,
-                RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
-                NotificationWakeUpCoordinator notificationWakeUpCoordinator,
-                KeyguardBypassController keyguardBypassController) {
-            mStatusBarKeyguardViewManager = man;
-            mKeyguardIndicationController = key;
-            mStackScroller = stack;
-            mPowerManager = pm;
-            mNotificationPanel = panelView;
-            mBarService = barService;
-            mNotificationListener = notificationListener;
-            mNotificationLogger = notificationLogger;
-            mWakefulnessLifecycle = createAwakeWakefulnessLifecycle();
-            mVisualStabilityManager = visualStabilityManager;
-            mViewHierarchyManager = viewHierarchyManager;
-            mEntryManager = entryManager;
-            mScrimController = scrimController;
-            mBiometricUnlockController = biometricUnlockController;
-            mKeyguardViewMediator = keyguardViewMediator;
-            mRemoteInputManager = notificationRemoteInputManager;
-            mGroupManager = notificationGroupManager;
-            mGroupAlertTransferHelper = notificationGroupAlertTransferHelper;
-            mFalsingManager = falsingManager;
-            mStatusBarWindowController = statusBarWindowController;
-            mNotificationIconAreaController = notificationIconAreaController;
-            mDozeScrimController = dozeScrimController;
-            mNotificationShelf = notificationShelf;
-            mLockscreenUserManager = notificationLockscreenUserManager;
-            mCommandQueue = commandQueue;
-            mPresenter = notificationPresenter;
-            mGestureWakeLock = mock(PowerManager.WakeLock.class);
-            mBubbleController = bubbleController;
-            mNavigationBarController = navBarController;
-            mAutoHideController = autoHideController;
-            mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-            mStatusBarWindow = statusBarWindow;
-            mDozeServiceHost.mWakeLockScreenPerformsAuth = false;
-            mBroadcastDispatcher = broadcastDispatcher;
-            mAssistManager = assistManager;
-            mGutsManager = notificationGutsManager;
-            mMediaManager = notificationMediaManager;
-            mForegroundServiceController = foregroundServiceController;
-            mAppOpsController = appOpsController;
-            mStatusBarStateController = statusBarStateController;
-            mDeviceProvisionedController = deviceProvisionedController;
-            mNotificationAlertingManager = notificationAlertingManager;
-            mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
-            mMetricsLogger = metricsLogger;
-            mHeadsUpManager = headsUpManager;
-            mKeyguardStateController = keyguardStateController;
-            mScreenLifecycle = screenLifecycle;
-            mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
-            mColorExtractor = colorExtractor;
-            mDisplayMetrics = displayMetrics;
-            mUiOffloadThread = uiOffloadThread;
-            mDozeLog = dozeLog;
-            mPulseExpansionHandler = pulseExpansionHandler;
-            mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler;
-            mWakeUpCoordinator = notificationWakeUpCoordinator;
-            mKeyguardBypassController = keyguardBypassController;
-        }
-
-        private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
-            WakefulnessLifecycle wakefulnessLifecycle = new WakefulnessLifecycle();
-            wakefulnessLifecycle.dispatchStartedWakingUp();
-            wakefulnessLifecycle.dispatchFinishedWakingUp();
-            return wakefulnessLifecycle;
-        }
-
-        @Override
-        protected void updateTheme() {
-            // Do nothing for now, until we have more mocking and StatusBar is smaller.
-        }
-
-        public void setBarStateForTest(int state) {
-            mState = state;
-        }
-
-        public void setUserSetupForTest(boolean userSetup) {
-            mUserSetup = userSetup;
-        }
-
-    }
-
     public static class TestableNotificationEntryManager extends NotificationEntryManager {
 
         public TestableNotificationEntryManager(Context context) {
@@ -969,7 +881,7 @@
     public static class TestableNotificationInterruptionStateProvider extends
             NotificationInterruptionStateProvider {
 
-        public TestableNotificationInterruptionStateProvider(
+        TestableNotificationInterruptionStateProvider(
                 Context context,
                 PowerManager powerManager,
                 IDreamManager dreamManager,
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/gestures/AccessibilityGestureDetector.java
index 7e8fb29..3dfe59e 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/AccessibilityGestureDetector.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/AccessibilityGestureDetector.java
@@ -408,9 +408,6 @@
         cancelGesture();
     }
 
-    public boolean firstTapDetected() {
-        return mFirstTapDetected;
-    }
 
     @Override
     public void onLongPress(MotionEvent e) {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index c60e35e..b62e260 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -411,24 +411,12 @@
         // we resent the delayed callback and wait again.
         mSendHoverEnterAndMoveDelayed.cancel();
         mSendHoverExitDelayed.cancel();
-
         // If a touch exploration gesture is in progress send events for its end.
         if (mState.isTouchExploring()) {
             sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
         }
 
-        // Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double
-        // tap.
-        if (!mGestureDetector.firstTapDetected() && mState.isClear()) {
-            mSendTouchExplorationEndDelayed.forceSendAndRemove();
-            mSendTouchInteractionEndDelayed.forceSendAndRemove();
-            mDispatcher.sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
-        } else {
-            // Let gesture to handle to avoid duplicated TYPE_TOUCH_INTERACTION_END event.
-            mSendTouchInteractionEndDelayed.cancel();
-        }
-
-        if (!mGestureDetector.firstTapDetected() && !mState.isTouchExploring()) {
+        if (mState.isClear()) {
             if (!mSendHoverEnterAndMoveDelayed.isPending()) {
                 // Queue a delayed transition to STATE_TOUCH_EXPLORING.
                 // If we do not detect that this is a gesture, delegation or drag the transition
@@ -441,6 +429,12 @@
                 // Cache the event until we discern exploration from gesturing.
                 mSendHoverEnterAndMoveDelayed.addEvent(event, rawEvent);
             }
+            mSendTouchExplorationEndDelayed.forceSendAndRemove();
+            mSendTouchInteractionEndDelayed.forceSendAndRemove();
+            mDispatcher.sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
+        } else {
+            // Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double tap.
+            mSendTouchInteractionEndDelayed.cancel();
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ee98af4..7cbd1fc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9736,6 +9736,10 @@
             sb.append("Foreground: ")
                     .append(process.isInterestingToUserLocked() ? "Yes" : "No")
                     .append("\n");
+            if (process.startTime > 0) {
+                long runtimeMillis = SystemClock.elapsedRealtime() - process.startTime;
+                sb.append("Process-Runtime: ").append(runtimeMillis).append("\n");
+            }
         }
         if (activityShortComponentName != null) {
             sb.append("Activity: ").append(activityShortComponentName).append("\n");
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 8e4474c..17541911 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1184,7 +1184,7 @@
                     updateStartedUserArrayLU();
                 }
                 needStart = true;
-                t.traceBegin("updateStateStopping");
+                t.traceEnd();
             }
 
             if (uss.state == UserState.STATE_BOOTING) {
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 8e09d0e..852b26d 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -47,7 +47,8 @@
 
     @Override
     public void reportChange(long changeId, ApplicationInfo appInfo) {
-        reportChange(changeId, appInfo, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
+        reportChange(changeId, appInfo.uid,
+                StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     @Override
@@ -60,13 +61,18 @@
     }
 
     @Override
+    public void reportChangeByUid(long changeId, int uid) {
+        reportChange(changeId, uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
+    }
+
+    @Override
     public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
         if (CompatConfig.get().isChangeEnabled(changeId, appInfo)) {
-            reportChange(changeId, appInfo,
+            reportChange(changeId, appInfo.uid,
                     StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
             return true;
         }
-        reportChange(changeId, appInfo,
+        reportChange(changeId, appInfo.uid,
                 StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__DISABLED);
         return false;
     }
@@ -81,6 +87,19 @@
     }
 
     @Override
+    public boolean isChangeEnabledByUid(long changeId, int uid) {
+        String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
+        if (packages == null || packages.length == 0) {
+            return true;
+        }
+        boolean enabled = true;
+        for (String packageName : packages) {
+            enabled = enabled && isChangeEnabledByPackageName(changeId, packageName);
+        }
+        return enabled;
+    }
+
+    @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
         CompatConfig.get().dumpConfig(pw);
@@ -95,8 +114,7 @@
         return null;
     }
 
-    private void reportChange(long changeId, ApplicationInfo appInfo, int state) {
-        int uid = appInfo.uid;
+    private void reportChange(long changeId, int uid, int state) {
         mChangeReporter.reportChange(uid, changeId, state);
     }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 4f4baab..61d4d4b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -850,36 +850,25 @@
                         mAddress, Constants.ADDR_BROADCAST, systemAudioStatusOn));
 
         if (systemAudioStatusOn) {
+            // If TV sends out SAM Request with a path of a non-CEC device, which should not show
+            // up in the CEC device list and not under the current AVR device, the AVR would switch
+            // to ARC.
             int sourcePhysicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
-            if (sourcePhysicalAddress != getActiveSource().physicalAddress) {
-                // If the Active Source recorded by the current device is not synced up with TV,
-                // update the Active Source internally.
-                if (sourcePhysicalAddress == mService.getPhysicalAddress()) {
-                    // If the active path is the current device itself, update with local info
-                    if (mService.playback() != null) {
-                        setActiveSource(mService.playback().mAddress, sourcePhysicalAddress);
-                    } else {
-                        setActiveSource(mAddress, sourcePhysicalAddress);
-                    }
-                } else {
-                    // If it's not the current device, look for the device info from the list
-                    for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) {
-                        if (info.getPhysicalAddress() == sourcePhysicalAddress) {
-                            setActiveSource(info.getLogicalAddress(), info.getPhysicalAddress());
-                            break;
-                        }
-                    }
-                }
-                // If the Active path from TV's System Audio Mode request does not belong to any
-                // device in the local device list, record the new Active physicalAddress with an
-                // unregistered logical address first. Then query the Active Source again.
-                if (sourcePhysicalAddress != getActiveSource().physicalAddress) {
-                    setActiveSource(Constants.ADDR_UNREGISTERED, sourcePhysicalAddress);
-                    mService.sendCecCommand(
-                        HdmiCecMessageBuilder.buildRequestActiveSource(mAddress));
+            if (HdmiUtils.getLocalPortFromPhysicalAddress(
+                    sourcePhysicalAddress, getDeviceInfo().getPhysicalAddress())
+                            != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE) {
+                return true;
+            }
+            boolean isDeviceInCecDeviceList = false;
+            for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) {
+                if (info.getPhysicalAddress() == sourcePhysicalAddress) {
+                    isDeviceInCecDeviceList = true;
+                    break;
                 }
             }
-            switchInputOnReceivingNewActivePath(sourcePhysicalAddress);
+            if (!isDeviceInCecDeviceList) {
+                switchInputOnReceivingNewActivePath(sourcePhysicalAddress);
+            }
         }
         return true;
     }
diff --git a/services/core/java/com/android/server/integrity/TEST_MAPPING b/services/core/java/com/android/server/integrity/TEST_MAPPING
new file mode 100644
index 0000000..b45b4ea
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/TEST_MAPPING
@@ -0,0 +1,18 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.integrity."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
new file mode 100644
index 0000000..fc44306
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.engine;
+
+import com.android.server.integrity.model.Rule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The engine used to evaluate rules against app installs.
+ *
+ * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
+ * to allow/block that install.
+ */
+public final class RuleEvaluationEngine {
+    private static final String TAG = "RuleEvaluation";
+
+    // The engine for loading rules, retrieving metadata for app installs, and evaluating app
+    // installs against rules.
+    private static RuleEvaluationEngine sRuleEvaluationEngine;
+
+    // The subset of rules loaded to be used to evaluate an app install request.
+    // TODO: Load rules relevant to app installs.
+    private List<Rule> mRules;
+
+    private RuleEvaluationEngine() {
+        // Initialize rules with the empty rule set.
+        mRules = new ArrayList<>();
+    }
+
+    /**
+     * Provide a singleton instance of the rule evaluation engine.
+     */
+    public static synchronized RuleEvaluationEngine getRuleEvaluationEngine() {
+        if (sRuleEvaluationEngine == null) {
+            return new RuleEvaluationEngine();
+        }
+        return sRuleEvaluationEngine;
+    }
+}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleLoader.java b/services/core/java/com/android/server/integrity/engine/RuleLoader.java
new file mode 100644
index 0000000..af24d7a
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/engine/RuleLoader.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.engine;
+
+import com.android.server.integrity.model.Rule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A helper class for loading rules to the rule evaluation engine.
+ *
+ * <p>Expose fine-grained APIs for loading rules to be passed to the rule evaluation engine.
+ *
+ * <p>It supports:
+ * <ul>
+ *     <li>Loading rules based on some keys, such as PACKAGE_NAME and APP_CERT.</li>
+ * </ul>
+ *
+ * <p>It does NOT support:
+ * <ul>
+ *     <li>Loading the list of all rules.</li>
+ *     <li>Merging rules resulting from different APIs.</li>
+ * </ul>
+ */
+final class RuleLoader {
+
+    List<Rule> loadRulesByPackageName(String packageName) {
+        // TODO: Add logic based on rule storage.
+        return new ArrayList<>();
+    }
+
+    List<Rule> loadRulesByAppCertificate(String appCertificate) {
+        // TODO: Add logic based on rule storage.
+        return new ArrayList<>();
+    }
+
+    List<Rule> loadRulesByInstallerName(String installerName) {
+        // TODO: Add logic based on rule storage.
+        return new ArrayList<>();
+    }
+
+    List<Rule> loadRulesByInstallerCertificate(String installerCertificate) {
+        // TODO: Add logic based on rule storage.
+        return new ArrayList<>();
+    }
+}
diff --git a/services/core/java/com/android/server/integrity/engine/AppInstallMetadata.java b/services/core/java/com/android/server/integrity/model/AppInstallMetadata.java
similarity index 91%
rename from services/core/java/com/android/server/integrity/engine/AppInstallMetadata.java
rename to services/core/java/com/android/server/integrity/model/AppInstallMetadata.java
index c2ed3df..814b8e1 100644
--- a/services/core/java/com/android/server/integrity/engine/AppInstallMetadata.java
+++ b/services/core/java/com/android/server/integrity/model/AppInstallMetadata.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.integrity.engine;
+package com.android.server.integrity.model;
 
 /**
  * The app install metadata.
@@ -32,7 +32,7 @@
     final int mVersionCode;
     final boolean mIsPreInstalled;
 
-    AppInstallMetadata(String packageName, String appCertificate, String installerName,
+    public AppInstallMetadata(String packageName, String appCertificate, String installerName,
             String installerCertificate, int versionCode, boolean isPreInstalled) {
         this.mPackageName = packageName;
         this.mAppCertificate = appCertificate;
diff --git a/services/core/java/com/android/server/integrity/model/Rule.java b/services/core/java/com/android/server/integrity/model/Rule.java
new file mode 100644
index 0000000..a6e08d8
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/Rule.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.model;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.Nullable;
+
+/**
+ * Represent rules to be used in the rule evaluation engine to match against app installs.
+ *
+ * <p>Instances of this class are immutable.
+ */
+public final class Rule {
+
+    // Holds an empty rule instance.
+    public static final Rule EMPTY = new Rule();
+
+    enum Key {
+        PACKAGE_NAME,
+        APP_CERTIFICATE,
+        INSTALLER_NAME,
+        INSTALLER_CERTIFICATE,
+        VERSION_CODE,
+        PRE_INSTALLED
+    }
+
+    enum Effect {
+        DENY
+    }
+
+    enum Operator {
+        EQ,
+        LT,
+        LE,
+        GT,
+        GE
+    }
+
+    enum Connector {
+        AND,
+        OR,
+        NOT
+    }
+
+    private final Formula mFormula;
+    private final Effect mEffect;
+
+    private Rule() {
+        this.mFormula = null;
+        this.mEffect = null;
+    }
+
+    public Rule(Formula formula, Effect effect) {
+        this.mFormula = checkNotNull(formula);
+        this.mEffect = checkNotNull(effect);
+    }
+
+    /**
+     * Indicates whether the rule is empty or not.
+     *
+     * @return {@code true} if the rule is empty, and {@code false} otherwise.
+     */
+    public boolean isEmpty() {
+        return mFormula == null && mEffect == null;
+    }
+
+    public Formula getFormula() {
+        return mFormula;
+    }
+
+    public Effect getEffect() {
+        return mEffect;
+    }
+
+    // TODO: Consider moving the sub-components to their respective model class.
+
+    /**
+     * Represents a rule logic/content.
+     */
+    abstract static class Formula {
+
+    }
+
+    /**
+     * Represents a simple formula consisting of an app install metadata field and a value.
+     */
+    public static final class AtomicFormula extends Formula {
+
+        final Key mKey;
+        final Operator mOperator;
+
+        // The value of a key can take either 1 of 3 forms: String, Integer, or Boolean.
+        // It cannot have multiple values.
+        @Nullable
+        final String mStringValue;
+        @Nullable
+        final Integer mIntValue;
+        @Nullable
+        final Boolean mBoolValue;
+
+        public AtomicFormula(Key key, Operator operator, String stringValue) {
+            // TODO: Add validators
+            this.mKey = key;
+            this.mOperator = operator;
+            this.mStringValue = stringValue;
+            this.mIntValue = null;
+            this.mBoolValue = null;
+        }
+
+        public AtomicFormula(Key key, Operator operator, Integer intValue) {
+            // TODO: Add validators
+            this.mKey = key;
+            this.mOperator = operator;
+            this.mStringValue = null;
+            this.mIntValue = intValue;
+            this.mBoolValue = null;
+        }
+
+        public AtomicFormula(Key key, Operator operator, Boolean boolValue) {
+            // TODO: Add validators
+            this.mKey = key;
+            this.mOperator = operator;
+            this.mStringValue = null;
+            this.mIntValue = null;
+            this.mBoolValue = boolValue;
+        }
+    }
+
+    /**
+     * Represents a complex formula consisting of other simple and complex formulas.
+     */
+    public static final class OpenFormula extends Formula {
+
+        final Connector mConnector;
+        final Formula mMainFormula;
+        final Formula mAuxiliaryFormula;
+
+        public OpenFormula(Connector connector, Formula mainFormula,
+                @Nullable Formula auxiliaryFormula) {
+            this.mConnector = checkNotNull(connector);
+            this.mMainFormula = checkNotNull(mainFormula);
+            this.mAuxiliaryFormula = auxiliaryFormula;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 378d9eb..bad484f 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -61,7 +61,10 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.hardware.authsecret.V1_0.IAuthSecret;
 import android.hardware.biometrics.BiometricManager;
+import android.hardware.face.Face;
 import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -117,6 +120,7 @@
 import com.android.internal.widget.LockSettingsInternal;
 import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.server.LocalServices;
+import com.android.server.ServiceThread;
 import com.android.server.SystemService;
 import com.android.server.locksettings.LockSettingsStorage.CredentialHash;
 import com.android.server.locksettings.LockSettingsStorage.PersistentData;
@@ -387,8 +391,15 @@
             return mContext;
         }
 
-        public Handler getHandler() {
-            return new Handler();
+        public ServiceThread getServiceThread() {
+            ServiceThread handlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
+                    true /*allowIo*/);
+            handlerThread.start();
+            return handlerThread;
+        }
+
+        public Handler getHandler(ServiceThread handlerThread) {
+            return new Handler(handlerThread.getLooper());
         }
 
         public LockSettingsStorage getStorage() {
@@ -483,6 +494,23 @@
         public boolean isGsiRunning() {
             return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0;
         }
+
+        public FingerprintManager getFingerprintManager() {
+            if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+                return (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE);
+            } else {
+                return null;
+            }
+        }
+
+        public FaceManager getFaceManager() {
+            if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
+                return (FaceManager) mContext.getSystemService(Context.FACE_SERVICE);
+            } else {
+                return null;
+            }
+        }
+
     }
 
     public LockSettingsService(Context context) {
@@ -495,7 +523,7 @@
         mContext = injector.getContext();
         mKeyStore = injector.getKeyStore();
         mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(mKeyStore);
-        mHandler = injector.getHandler();
+        mHandler = injector.getHandler(injector.getServiceThread());
         mStrongAuth = injector.getStrongAuth();
         mActivityManager = injector.getActivityManager();
 
@@ -2713,6 +2741,7 @@
             fixateNewestUserKeyAuth(userId);
             unlockKeystore(auth.deriveKeyStorePassword(), userId);
             setKeystorePassword(null, userId);
+            removeBiometricsForUser(userId);
         }
         setSyntheticPasswordHandleLocked(newHandle, userId);
         synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
@@ -2728,6 +2757,85 @@
         return newHandle;
     }
 
+    private void removeBiometricsForUser(int userId) {
+        removeAllFingerprintForUser(userId);
+        removeAllFaceForUser(userId);
+    }
+
+    private void removeAllFingerprintForUser(final int userId) {
+        FingerprintManager mFingerprintManager = mInjector.getFingerprintManager();
+        if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
+            if (mFingerprintManager.hasEnrolledFingerprints(userId)) {
+                mFingerprintManager.setActiveUser(userId);
+                CountDownLatch latch = new CountDownLatch(1);
+                // For the purposes of M and N, groupId is the same as userId.
+                Fingerprint finger = new Fingerprint(null, userId, 0, 0);
+                mFingerprintManager.remove(finger, userId,
+                        fingerprintManagerRemovalCallback(latch));
+                try {
+                    latch.await(10000, TimeUnit.MILLISECONDS);
+                } catch (InterruptedException e) {
+                    Slog.e(TAG, "Latch interrupted when removing fingerprint", e);
+                }
+            }
+        }
+    }
+
+    private void removeAllFaceForUser(final int userId) {
+        FaceManager mFaceManager = mInjector.getFaceManager();
+        if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
+            if (mFaceManager.hasEnrolledTemplates(userId)) {
+                mFaceManager.setActiveUser(userId);
+                CountDownLatch latch = new CountDownLatch(1);
+                Face face = new Face(null, 0, 0);
+                mFaceManager.remove(face, userId, faceManagerRemovalCallback(latch));
+                try {
+                    latch.await(10000, TimeUnit.MILLISECONDS);
+                } catch (InterruptedException e) {
+                    Slog.e(TAG, "Latch interrupted when removing face", e);
+                }
+            }
+        }
+    }
+
+    private FingerprintManager.RemovalCallback fingerprintManagerRemovalCallback(
+            CountDownLatch latch) {
+        return new FingerprintManager.RemovalCallback() {
+            @Override
+            public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence err) {
+                Slog.e(TAG, String.format(
+                        "Can't remove fingerprint %d in group %d. Reason: %s",
+                        fp.getBiometricId(), fp.getGroupId(), err));
+                latch.countDown();
+            }
+
+            @Override
+            public void onRemovalSucceeded(Fingerprint fp, int remaining) {
+                if (remaining == 0) {
+                    latch.countDown();
+                }
+            }
+        };
+    }
+
+    private FaceManager.RemovalCallback faceManagerRemovalCallback(CountDownLatch latch) {
+        return new FaceManager.RemovalCallback() {
+            @Override
+            public void onRemovalError(Face face, int errMsgId, CharSequence err) {
+                Slog.e(TAG, String.format("Can't remove face %d. Reason: %s",
+                        face.getBiometricId(), err));
+                latch.countDown();
+            }
+
+            @Override
+            public void onRemovalSucceeded(Face face, int remaining) {
+                if (remaining == 0) {
+                    latch.countDown();
+                }
+            }
+        };
+    }
+
     @GuardedBy("mSpManager")
     private boolean spBasedSetLockCredentialInternalLocked(byte[] credential, int credentialType,
             byte[] savedCredential, int requestedQuality, int userId,
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 043c834..668f2be 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageManager;
 import android.media.IMediaRouter2Client;
 import android.media.IMediaRouter2Manager;
+import android.media.IMediaRouterClient;
 import android.media.MediaRoute2Info;
 import android.media.MediaRoute2ProviderInfo;
 import android.os.Binder;
@@ -86,7 +87,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                registerClientLocked(client, uid, pid, packageName, userId, trusted);
+                registerClient2Locked(client, uid, pid, packageName, userId, trusted);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -99,7 +100,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                unregisterClientLocked(client, false);
+                unregisterClient2Locked(client, false);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -155,14 +156,30 @@
         }
     }
 
-    public void setControlCategories(@NonNull IMediaRouter2Client client,
+    //TODO: What would happen if a media app used MediaRouter and MediaRouter2 simultaneously?
+    public void setControlCategories(@NonNull IMediaRouterClient client,
+            @Nullable List<String> categories) {
+        Objects.requireNonNull(client, "client must not be null");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
+                setControlCategoriesLocked(clientRecord, categories);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    public void setControlCategories2(@NonNull IMediaRouter2Client client,
             @Nullable List<String> categories) {
         Objects.requireNonNull(client, "client must not be null");
 
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                setControlCategoriesLocked(client, categories);
+                ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
+                setControlCategoriesLocked(clientRecord, categories);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -174,7 +191,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                selectRoute2Locked(client, route);
+                selectRoute2Locked(mAllClientRecords.get(client.asBinder()), route);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -193,6 +210,36 @@
         }
     }
 
+    public void registerClient(@NonNull IMediaRouterClient client, @NonNull String packageName) {
+        Objects.requireNonNull(client, "client must not be null");
+
+        final int uid = Binder.getCallingUid();
+        final int pid = Binder.getCallingPid();
+        final int userId = UserHandle.getUserId(uid);
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                registerClient1Locked(client, packageName, userId);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    public void unregisterClient(@NonNull IMediaRouterClient client) {
+        Objects.requireNonNull(client, "client must not be null");
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                unregisterClient1Locked(client);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     //TODO: Review this is handling multi-user properly.
     void switchUser() {
         synchronized (mLock) {
@@ -217,9 +264,9 @@
         }
     }
 
-    void clientDied(ClientRecord clientRecord) {
+    void clientDied(Client2Record clientRecord) {
         synchronized (mLock) {
-            unregisterClientLocked(clientRecord.mClient, true);
+            unregisterClient2Locked(clientRecord.mClient, true);
         }
     }
 
@@ -229,18 +276,18 @@
         }
     }
 
-    private void registerClientLocked(IMediaRouter2Client client,
+    private void registerClient2Locked(IMediaRouter2Client client,
             int uid, int pid, String packageName, int userId, boolean trusted) {
         final IBinder binder = client.asBinder();
-        ClientRecord clientRecord = mAllClientRecords.get(binder);
-        if (clientRecord == null) {
+        if (mAllClientRecords.get(binder) == null) {
             boolean newUser = false;
             UserRecord userRecord = mUserRecords.get(userId);
             if (userRecord == null) {
                 userRecord = new UserRecord(userId);
                 newUser = true;
             }
-            clientRecord = new ClientRecord(userRecord, client, uid, pid, packageName, trusted);
+            Client2Record clientRecord = new Client2Record(userRecord, client, uid, pid,
+                    packageName, trusted);
             try {
                 binder.linkToDeath(clientRecord, 0);
             } catch (RemoteException ex) {
@@ -261,8 +308,8 @@
         }
     }
 
-    private void unregisterClientLocked(IMediaRouter2Client client, boolean died) {
-        ClientRecord clientRecord = mAllClientRecords.remove(client.asBinder());
+    private void unregisterClient2Locked(IMediaRouter2Client client, boolean died) {
+        Client2Record clientRecord = (Client2Record) mAllClientRecords.remove(client.asBinder());
         if (clientRecord != null) {
             UserRecord userRecord = clientRecord.mUserRecord;
             userRecord.mClientRecords.remove(clientRecord);
@@ -272,8 +319,7 @@
         }
     }
 
-    private void selectRoute2Locked(IMediaRouter2Client client, MediaRoute2Info route) {
-        ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
+    private void selectRoute2Locked(ClientRecord clientRecord, MediaRoute2Info route) {
         if (clientRecord != null) {
             MediaRoute2Info oldRoute = clientRecord.mSelectedRoute;
             clientRecord.mSelectedRoute = route;
@@ -294,10 +340,7 @@
         }
     }
 
-    private void setControlCategoriesLocked(IMediaRouter2Client client, List<String> categories) {
-        final IBinder binder = client.asBinder();
-        ClientRecord clientRecord = mAllClientRecords.get(binder);
-
+    private void setControlCategoriesLocked(ClientRecord clientRecord, List<String> categories) {
         if (clientRecord != null) {
             clientRecord.mControlCategories = categories;
 
@@ -349,9 +392,7 @@
                     obtainMessage(UserHandler::notifyProviderInfosUpdatedToManager,
                             userRecord.mHandler, manager));
 
-            final int count = userRecord.mClientRecords.size();
-            for (int i = 0; i < count; i++) {
-                ClientRecord clientRecord = userRecord.mClientRecords.get(i);
+            for (ClientRecord clientRecord : userRecord.mClientRecords) {
                 clientRecord.mUserRecord.mHandler.sendMessage(
                         obtainMessage(UserHandler::updateClientUsage,
                             clientRecord.mUserRecord.mHandler, clientRecord));
@@ -378,7 +419,7 @@
                 Slog.w(TAG, "Ignoring route selection for unknown client.");
             }
             if (clientRecord != null && managerRecord.mTrusted) {
-                selectRoute2Locked(clientRecord.mClient, route);
+                selectRoute2Locked(clientRecord, route);
             }
         }
     }
@@ -409,6 +450,37 @@
         }
     }
 
+    private void registerClient1Locked(IMediaRouterClient client, String packageName,
+            int userId) {
+        final IBinder binder = client.asBinder();
+        if (mAllClientRecords.get(binder) == null) {
+            boolean newUser = false;
+            UserRecord userRecord = mUserRecords.get(userId);
+            if (userRecord == null) {
+                userRecord = new UserRecord(userId);
+                newUser = true;
+            }
+            ClientRecord clientRecord = new Client1Record(userRecord, client, packageName);
+
+            if (newUser) {
+                mUserRecords.put(userId, userRecord);
+                initializeUserLocked(userRecord);
+            }
+
+            userRecord.mClientRecords.add(clientRecord);
+            mAllClientRecords.put(binder, clientRecord);
+        }
+    }
+
+    private void unregisterClient1Locked(IMediaRouterClient client) {
+        ClientRecord clientRecord = mAllClientRecords.remove(client.asBinder());
+        if (clientRecord != null) {
+            UserRecord userRecord = clientRecord.mUserRecord;
+            userRecord.mClientRecords.remove(clientRecord);
+            disposeUserIfNeededLocked(userRecord);
+        }
+    }
+
     final class UserRecord {
         public final int mUserId;
         final ArrayList<ClientRecord> mClientRecords = new ArrayList<>();
@@ -430,25 +502,43 @@
         }
     }
 
-    final class ClientRecord implements IBinder.DeathRecipient {
+    class ClientRecord {
         public final UserRecord mUserRecord;
-        public final IMediaRouter2Client mClient;
-        public final int mUid;
-        public final int mPid;
         public final String mPackageName;
-        public final boolean mTrusted;
         public List<String> mControlCategories;
         public MediaRoute2Info mSelectedRoute;
 
-        ClientRecord(UserRecord userRecord, IMediaRouter2Client client,
-                int uid, int pid, String packageName, boolean trusted) {
+        ClientRecord(UserRecord userRecord, String packageName) {
             mUserRecord = userRecord;
+            mPackageName = packageName;
+            mControlCategories = Collections.emptyList();
+        }
+    }
+
+    final class Client1Record extends ClientRecord {
+        public final IMediaRouterClient mClient;
+
+        Client1Record(UserRecord userRecord, IMediaRouterClient client,
+                String packageName) {
+            super(userRecord, packageName);
+            mClient = client;
+        }
+    }
+
+    final class Client2Record extends ClientRecord
+            implements IBinder.DeathRecipient {
+        public final IMediaRouter2Client mClient;
+        public final int mUid;
+        public final int mPid;
+        public final boolean mTrusted;
+
+        Client2Record(UserRecord userRecord, IMediaRouter2Client client,
+                int uid, int pid, String packageName, boolean trusted) {
+            super(userRecord, packageName);
             mClient = client;
             mUid = uid;
             mPid = pid;
-            mPackageName = packageName;
             mTrusted = trusted;
-            mControlCategories = Collections.emptyList();
         }
 
         public void dispose() {
@@ -622,7 +712,9 @@
                     managers.add(managerRecord.mManager);
                 }
                 for (ClientRecord clientRecord : mUserRecord.mClientRecords) {
-                    clients.add(clientRecord.mClient);
+                    if (clientRecord instanceof Client2Record) {
+                        clients.add(((Client2Record) clientRecord).mClient);
+                    }
                 }
             }
             for (IMediaRouter2Manager manager : managers) {
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 2670cd8..796a25d 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -249,6 +249,7 @@
             synchronized (mLock) {
                 registerClientLocked(client, uid, pid, packageName, resolvedUserId, trusted);
             }
+            mService2.registerClient(client, packageName);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -289,6 +290,7 @@
             synchronized (mLock) {
                 unregisterClientLocked(client, false);
             }
+            mService2.unregisterClient(client);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -395,6 +397,12 @@
 
     // Binder call
     @Override
+    public void setControlCategories(IMediaRouterClient client, List<String> controlCategories) {
+        mService2.setControlCategories(client, controlCategories);
+    }
+
+    // Binder call
+    @Override
     public void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction) {
         if (client == null) {
             throw new IllegalArgumentException("client must not be null");
@@ -487,8 +495,8 @@
 
     // Binder call
     @Override
-    public void setControlCategories(IMediaRouter2Client client, List<String> categories) {
-        mService2.setControlCategories(client, categories);
+    public void setControlCategories2(IMediaRouter2Client client, List<String> categories) {
+        mService2.setControlCategories2(client, categories);
     }
 
     void restoreBluetoothA2dp() {
@@ -561,6 +569,7 @@
         synchronized (mLock) {
             unregisterClientLocked(clientRecord.mClient, true);
         }
+        mService2.unregisterClient(clientRecord.mClient);
     }
 
     private void registerClientLocked(IMediaRouterClient client,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
old mode 100644
new mode 100755
index d480cb6e..a8ba82a
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1331,16 +1331,15 @@
                     uidList = new int[] {intent.getIntExtra(Intent.EXTRA_UID, -1)};
                 }
                 if (pkgList != null && (pkgList.length > 0)) {
-                    for (String pkgName : pkgList) {
-                        if (cancelNotifications) {
+                    if (cancelNotifications) {
+                        for (String pkgName : pkgList) {
                             cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, null, 0, 0,
                                     !queryRestart, changeUserId, reason, null);
-                        } else if (hideNotifications) {
-                            hideNotificationsForPackages(pkgList);
-                        } else if (unhideNotifications) {
-                            unhideNotificationsForPackages(pkgList);
                         }
-
+                    } else if (hideNotifications) {
+                        hideNotificationsForPackages(pkgList);
+                    } else if (unhideNotifications) {
+                        unhideNotificationsForPackages(pkgList);
                     }
                 }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 8b24224..a7d4237 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -259,6 +259,10 @@
         // Don't hold mSessions lock when calling restoreSession, since it might trigger an APK
         // atomic install which needs to query sessions, which requires lock on mSessions.
         for (PackageInstallerSession session : stagedSessionsToRestore) {
+            if (mPm.isDeviceUpgrading()) {
+                session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+                        "Build fingerprint has changed");
+            }
             mStagingManager.restoreSession(session);
         }
         // Broadcasts are not sent while we restore sessions on boot, since no processes would be
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 282fed8..aac0f90 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -51,7 +51,6 @@
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.service.sms.FinancialSmsService;
-import android.telephony.IFinancialSmsCallback;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -702,40 +701,6 @@
             dumpOutputStream.flush();
         }
 
-        /**
-         * Get filtered SMS messages for financial app.
-         */
-        @Override
-        public void getSmsMessagesForFinancialApp(
-                String callingPkg, Bundle params, IFinancialSmsCallback callback) {
-            int mode = PermissionChecker.checkCallingOrSelfPermission(
-                    getContext(),
-                    AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS);
-
-            if (mode == PermissionChecker.PERMISSION_GRANTED) {
-                FinancialSmsManager financialSmsManager = new FinancialSmsManager(getContext());
-                financialSmsManager.getSmsMessages(new RemoteCallback((result) -> {
-                    CursorWindow messages = null;
-                    if (result == null) {
-                        Slog.w(LOG_TAG, "result is null.");
-                    } else {
-                        messages = result.getParcelable(FinancialSmsService.EXTRA_SMS_MSGS);
-                    }
-                    try {
-                        callback.onGetSmsMessagesForFinancialApp(messages);
-                    } catch (RemoteException e) {
-                        // do nothing
-                    }
-                }), params);
-            } else {
-                try {
-                    callback.onGetSmsMessagesForFinancialApp(null);
-                } catch (RemoteException e) {
-                    // do nothing
-                }
-            }
-        }
-
         private int getUidForPackage(String packageName) {
             long ident = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index eadd09c..425da37 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -28,6 +28,7 @@
 import android.util.SparseLongArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import libcore.io.IoUtils;
 
@@ -288,19 +289,25 @@
             JSONObject dataJson = new JSONObject(
                     IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath()));
 
-            return new Rollback(
-                    rollbackInfoFromJson(dataJson.getJSONObject("info")),
-                    backupDir,
-                    Instant.parse(dataJson.getString("timestamp")),
-                    dataJson.getInt("stagedSessionId"),
-                    rollbackStateFromString(dataJson.getString("state")),
-                    dataJson.getInt("apkSessionId"),
-                    dataJson.getBoolean("restoreUserDataInProgress"));
+            return rollbackFromJson(dataJson, backupDir);
         } catch (JSONException | DateTimeParseException | ParseException e) {
             throw new IOException(e);
         }
     }
 
+    @VisibleForTesting
+    static Rollback rollbackFromJson(JSONObject dataJson, File backupDir)
+            throws JSONException, ParseException {
+        return new Rollback(
+                rollbackInfoFromJson(dataJson.getJSONObject("info")),
+                backupDir,
+                Instant.parse(dataJson.getString("timestamp")),
+                dataJson.getInt("stagedSessionId"),
+                rollbackStateFromString(dataJson.getString("state")),
+                dataJson.getInt("apkSessionId"),
+                dataJson.getBoolean("restoreUserDataInProgress"));
+    }
+
     private static JSONObject toJson(VersionedPackage pkg) throws JSONException {
         JSONObject json = new JSONObject();
         json.put("packageName", pkg.getPackageName());
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 4c93564..5493afd 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -365,10 +365,16 @@
     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, fout)) return;
         IndentingPrintWriter pw = new IndentingPrintWriter(fout, "  ");
-        TextClassificationManager tcm = mContext.getSystemService(TextClassificationManager.class);
-        tcm.dump(pw);
 
-        pw.printPair("context", mContext); pw.println();
+        // Create a TCM instance with the system server identity. TCM creates a ContentObserver
+        // to listen for settings changes. It does not pass the checkContentProviderAccess check
+        // if we are using the shell identity, because AMS does not track of processes spawn from
+        // shell.
+        Binder.withCleanCallingIdentity(
+                () -> mContext.getSystemService(TextClassificationManager.class).dump(pw));
+
+        pw.printPair("context", mContext);
+        pw.println();
         synchronized (mLock) {
             int size = mUserStates.size();
             pw.print("Number user states: "); pw.println(size);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c3ff285..b118cdf 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11902,10 +11902,13 @@
                     try {
                         int uid = packageManager.getPackageUidAsUser(packageName,
                                 user.getIdentifier());
-
-                        // TODO: Prevent noting the app-op
-                        granted = PermissionChecker.checkPermission(mContext, permission, -1,
-                                uid, packageName);
+                        if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
+                                PermissionChecker.PID_UNKNOWN, uid, packageName)
+                                        != PermissionChecker.PERMISSION_GRANTED) {
+                            granted = PackageManager.PERMISSION_DENIED;
+                        } else {
+                            granted = PackageManager.PERMISSION_GRANTED;
+                        }
                     } catch (NameNotFoundException e) {
                         throw new RemoteException(
                                 "Cannot check if " + permission + "is a runtime permission", e,
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
index 11bd29d..ad3e040 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
@@ -28,6 +28,7 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -114,6 +115,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void testSendMessage_notSuccess() {
         mSendCecCommandSuccess = false;
         mShouldDispatchReportArcTerminated = false;
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index a89198a..0a1899b 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -232,6 +232,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleGiveSystemAudioModeStatus_originalOff() throws Exception {
         HdmiCecMessage expectedMessage =
                 HdmiCecMessageBuilder.buildReportSystemAudioMode(
@@ -301,6 +302,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSetSystemAudioMode_setOn_orignalOff() throws Exception {
         mMusicMute = true;
         HdmiCecMessage messageSet =
@@ -328,6 +330,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSystemAudioModeRequest_turnOffByTv() throws Exception {
         assertThat(mMusicMute).isFalse();
         // Check if feature correctly turned off
@@ -497,6 +500,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleRequestArcTerminate_arcIsNotOn() throws Exception {
         assertThat(mHdmiCecLocalDeviceAudioSystem.isArcEnabled()).isFalse();
         HdmiCecMessage message =
@@ -671,6 +675,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleReportPhysicalAddress_differentPath_addDevice() {
         assertThat(mInvokeDeviceEventState).isNotEqualTo(DEVICE_EVENT_ADD_DEVICE);
         HdmiDeviceInfo oldDevice = new HdmiDeviceInfo(
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index b8799c3..0062a17 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -99,6 +99,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSetSystemAudioModeOn_audioSystemBroadcast() {
         mHdmiControlService.setSystemAudioActivated(false);
         assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse();
@@ -110,6 +111,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSetSystemAudioModeOff_audioSystemToPlayback() {
         mHdmiCecLocalDevicePlayback.mService.setSystemAudioActivated(true);
         assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue();
@@ -123,6 +125,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void handleSystemAudioModeStatusOn_DirectltToLocalDeviceFromAudioSystem() {
         mHdmiControlService.setSystemAudioActivated(false);
         assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
index 440a49a..6dcff35 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
@@ -221,6 +221,7 @@
     }
 
     @Test
+    @Ignore("b/120845532")
     public void testTvSupport() {
         resetTestVariables();
         mShouldDispatchActiveSource = true;
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/RuleTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/RuleTest.java
new file mode 100644
index 0000000..4321c21
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/model/RuleTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.model;
+
+import static com.android.server.testutils.TestUtils.assertExpectException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class RuleTest {
+
+    private static final Rule.Effect DENY_EFFECT = Rule.Effect.DENY;
+    private static final Rule.Formula SIMPLE_FORMULA =
+            new Rule.AtomicFormula(Rule.Key.PACKAGE_NAME, Rule.Operator.EQ, "com.test.app");
+
+    @Test
+    public void testEmptyRule() {
+        Rule emptyRule = Rule.EMPTY;
+
+        assertNull(emptyRule.getFormula());
+        assertNull(emptyRule.getEffect());
+    }
+
+    @Test
+    public void testValidRule() {
+        Rule validRule = new Rule(SIMPLE_FORMULA, DENY_EFFECT);
+
+        assertEquals(SIMPLE_FORMULA, validRule.getFormula());
+        assertEquals(DENY_EFFECT, validRule.getEffect());
+    }
+
+    @Test
+    public void testInvalidRule_invalidEffect() {
+        assertExpectException(
+                NullPointerException.class,
+                /* expectedExceptionMessageRegex */ null,
+                () -> new Rule(SIMPLE_FORMULA, null));
+    }
+
+    @Test
+    public void testInvalidRule_invalidFormula() {
+        assertExpectException(
+                NullPointerException.class,
+                /* expectedExceptionMessageRegex */ null,
+                () -> new Rule(null, DENY_EFFECT));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index 7cece1f..f9ac022 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -32,8 +32,11 @@
 import android.app.admin.DeviceStateCache;
 import android.app.trust.TrustManager;
 import android.content.ComponentName;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.hardware.authsecret.V1_0.IAuthSecret;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.FileUtils;
 import android.os.IProgressListener;
 import android.os.RemoteException;
@@ -95,6 +98,9 @@
     RecoverableKeyStoreManager mRecoverableKeyStoreManager;
     UserManagerInternal mUserManagerInternal;
     DeviceStateCache mDeviceStateCache;
+    FingerprintManager mFingerprintManager;
+    FaceManager mFaceManager;
+    PackageManager mPackageManager;
     protected boolean mHasSecureLockScreen;
 
     @Override
@@ -114,6 +120,9 @@
         mRecoverableKeyStoreManager = mock(RecoverableKeyStoreManager.class);
         mUserManagerInternal = mock(UserManagerInternal.class);
         mDeviceStateCache = mock(DeviceStateCache.class);
+        mFingerprintManager = mock(FingerprintManager.class);
+        mFaceManager = mock(FaceManager.class);
+        mPackageManager = mock(PackageManager.class);
 
         LocalServices.removeServiceForTest(LockSettingsInternal.class);
         LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
@@ -123,7 +132,7 @@
 
         mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager,
                 mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class),
-                mock(KeyguardManager.class));
+                mock(KeyguardManager.class), mFingerprintManager, mFaceManager, mPackageManager);
         mStorage = new LockSettingsStorageTestable(mContext,
                 new File(getContext().getFilesDir(), "locksettings"));
         File storageDir = mStorage.mStorageDir;
@@ -181,6 +190,8 @@
                 new ComponentName("com.dummy.package", ".FakeDeviceOwner"));
         when(mUserManagerInternal.isDeviceManaged()).thenReturn(true);
         when(mDeviceStateCache.isDeviceProvisioned()).thenReturn(true);
+        mockBiometricsHardwareFingerprintsAndTemplates(PRIMARY_USER_ID);
+        mockBiometricsHardwareFingerprintsAndTemplates(MANAGED_PROFILE_USER_ID);
 
         mLocalService = LocalServices.getService(LockSettingsInternal.class);
     }
@@ -233,6 +244,18 @@
         return sm;
     }
 
+    private void mockBiometricsHardwareFingerprintsAndTemplates(int userId) {
+        // Hardware must be detected and fingerprints must be enrolled
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)).thenReturn(true);
+        when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+        when(mFingerprintManager.hasEnrolledFingerprints(userId)).thenReturn(true);
+
+        // Hardware must be detected and templates must be enrolled
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
+        when(mFaceManager.isHardwareDetected()).thenReturn(true);
+        when(mFaceManager.hasEnrolledTemplates(userId)).thenReturn(true);
+    }
+
     @Override
     protected void tearDown() throws Exception {
         super.tearDown();
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 65d6f45..fcd98e0 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -23,7 +23,6 @@
 import android.content.Context;
 import android.hardware.authsecret.V1_0.IAuthSecret;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserManagerInternal;
@@ -32,6 +31,7 @@
 import android.security.keystore.KeyPermanentlyInvalidatedException;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.server.ServiceThread;
 import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
 
 import java.io.FileNotFoundException;
@@ -70,8 +70,8 @@
         }
 
         @Override
-        public Handler getHandler() {
-            return new Handler(Looper.getMainLooper());
+        public Handler getHandler(ServiceThread handlerThread) {
+            return new Handler(handlerThread.getLooper());
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 7354ad4..5818133 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -330,6 +330,27 @@
                 .lockScreenSecretChanged(CREDENTIAL_TYPE_NONE, null, MANAGED_PROFILE_USER_ID);
     }
 
+    public void testSetLockCredential_nullCredential_removeBiometrics() throws RemoteException {
+        final String oldCredential = "oldPassword";
+
+        initializeStorageWithCredential(
+                PRIMARY_USER_ID,
+                oldCredential,
+                CREDENTIAL_TYPE_PATTERN,
+                PASSWORD_QUALITY_SOMETHING);
+        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
+
+        mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, oldCredential.getBytes(),
+                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
+
+        // Verify fingerprint is removed
+        verify(mFingerprintManager).remove(any(), eq(PRIMARY_USER_ID), any());
+        verify(mFaceManager).remove(any(), eq(PRIMARY_USER_ID), any());
+
+        verify(mFingerprintManager).remove(any(), eq(MANAGED_PROFILE_USER_ID), any());
+        verify(mFaceManager).remove(any(), eq(MANAGED_PROFILE_USER_ID), any());
+    }
+
     public void testSetLockCredential_forUnifiedToSeparateChallengeProfile_sendsNewCredentials()
             throws Exception {
         final String parentPassword = "parentPassword";
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index 8e0d7be..2a169b7 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -24,8 +24,11 @@
 import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.database.sqlite.SQLiteDatabase;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.FileUtils;
 import android.os.SystemClock;
 import android.os.UserManager;
@@ -86,7 +89,9 @@
 
         MockLockSettingsContext context = new MockLockSettingsContext(getContext(), mockUserManager,
                 mock(NotificationManager.class), mock(DevicePolicyManager.class),
-                mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class));
+                mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class),
+                mock(FingerprintManager.class), mock(FaceManager.class),
+                mock(PackageManager.class));
         mStorage = new LockSettingsStorageTestable(context,
                 new File(getContext().getFilesDir(), "locksettings"));
         mStorage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
index b332532..2b9a05c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
@@ -23,6 +23,8 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.PackageManager;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 
@@ -34,11 +36,15 @@
     private StorageManager mStorageManager;
     private TrustManager mTrustManager;
     private KeyguardManager mKeyguardManager;
+    private FingerprintManager mFingerprintManager;
+    private FaceManager mFaceManager;
+    private PackageManager mPackageManager;
 
     public MockLockSettingsContext(Context base, UserManager userManager,
             NotificationManager notificationManager, DevicePolicyManager devicePolicyManager,
             StorageManager storageManager, TrustManager trustManager,
-            KeyguardManager keyguardManager) {
+            KeyguardManager keyguardManager, FingerprintManager fingerprintManager,
+            FaceManager faceManager, PackageManager packageManager) {
         super(base);
         mUserManager = userManager;
         mNotificationManager = notificationManager;
@@ -46,6 +52,9 @@
         mStorageManager = storageManager;
         mTrustManager = trustManager;
         mKeyguardManager = keyguardManager;
+        mFingerprintManager = fingerprintManager;
+        mFaceManager = faceManager;
+        mPackageManager = packageManager;
     }
 
     @Override
@@ -62,12 +71,21 @@
             return mTrustManager;
         } else if (KEYGUARD_SERVICE.equals(name)) {
             return mKeyguardManager;
+        } else if (FINGERPRINT_SERVICE.equals(name)) {
+            return mFingerprintManager;
+        } else if (FACE_SERVICE.equals(name)) {
+            return mFaceManager;
         } else {
             throw new RuntimeException("System service not mocked: " + name);
         }
     }
 
     @Override
+    public PackageManager getPackageManager() {
+        return mPackageManager;
+    }
+
+    @Override
     public void enforceCallingOrSelfPermission(String permission, String message) {
         // Skip permission checks for unit tests.
     }
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
new file mode 100644
index 0000000..ee3b15a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.rollback;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.pm.VersionedPackage;
+import android.content.rollback.PackageRollbackInfo;
+import android.util.IntArray;
+import android.util.SparseLongArray;
+
+import com.google.common.truth.Correspondence;
+
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+@RunWith(JUnit4.class)
+public class RollbackStoreTest {
+
+    private static final int ID = 123;
+
+    private static final Correspondence<VersionedPackage, VersionedPackage> VER_PKG_CORR =
+            new Correspondence<VersionedPackage, VersionedPackage>() {
+                @Override
+                public boolean compare(VersionedPackage a, VersionedPackage b) {
+                    if (a == null || b == null) {
+                        return a == b;
+                    }
+                    return a.getLongVersionCode() == b.getLongVersionCode()
+                            && Objects.equals(a.getPackageName(), b.getPackageName());
+                }
+
+                @Override
+                public String toString() {
+                    return "is the same as";
+                }
+            };
+
+    private static final Correspondence<PackageRollbackInfo.RestoreInfo,
+            PackageRollbackInfo.RestoreInfo>
+            RESTORE_INFO_CORR =
+            new Correspondence<PackageRollbackInfo.RestoreInfo, PackageRollbackInfo.RestoreInfo>() {
+                @Override
+                public boolean compare(PackageRollbackInfo.RestoreInfo a,
+                        PackageRollbackInfo.RestoreInfo b) {
+                    if (a == null || b == null) {
+                        return a == b;
+                    }
+                    return a.userId == b.userId
+                            && a.appId == b.appId
+                            && Objects.equals(a.seInfo, b.seInfo);
+                }
+
+                @Override
+                public String toString() {
+                    return "is the same as";
+                }
+            };
+
+    private static final String JSON_ROLLBACK = "{'info':{'rollbackId':123,'packages':"
+            + "[{'versionRolledBackFrom':{'packageName':'blah','longVersionCode':55},"
+            + "'versionRolledBackTo':{'packageName':'blah1','longVersionCode':50},'pendingBackups':"
+            + "[59,1245,124544],'pendingRestores':[{'userId':498,'appId':32322,'seInfo':'wombles'},"
+            + "{'userId':-895,'appId':1,'seInfo':'pingu'}],'isApex':false,'installedUsers':"
+            + "[498468432,1111,98464],'ceSnapshotInodes':[{'userId':1,'ceSnapshotInode':-6},"
+            + "{'userId':2222,'ceSnapshotInode':81641654445},{'userId':546546,"
+            + "'ceSnapshotInode':345689375}]},{'versionRolledBackFrom':{'packageName':'chips',"
+            + "'longVersionCode':28},'versionRolledBackTo':{'packageName':'com.chips.test',"
+            + "'longVersionCode':48},'pendingBackups':[5],'pendingRestores':[{'userId':18,"
+            + "'appId':-12,'seInfo':''}],'isApex':false,'installedUsers':[55,79],"
+            + "'ceSnapshotInodes':[]}],'isStaged':false,'causePackages':[{'packageName':'hello',"
+            + "'longVersionCode':23},{'packageName':'something','longVersionCode':999}],"
+            + "'committedSessionId':45654465},'timestamp':'2019-10-01T12:29:08.855Z',"
+            + "'stagedSessionId':-1,'state':'enabling','apkSessionId':-1,"
+            + "'restoreUserDataInProgress':true}";
+
+    @Rule
+    public TemporaryFolder mFolder = new TemporaryFolder();
+
+    private File mRollbackDir;
+
+    private RollbackStore mRollbackStore;
+
+    @Before
+    public void setUp() throws Exception {
+        mRollbackStore = new RollbackStore(mFolder.getRoot());
+        mRollbackDir = mFolder.newFolder(ID + "");
+        mFolder.newFile("rollback.json");
+    }
+
+    @Test
+    public void createNonStaged() {
+        Rollback rollback = mRollbackStore.createNonStagedRollback(ID);
+
+        assertThat(rollback.getBackupDir().getAbsolutePath())
+                .isEqualTo(mFolder.getRoot().getAbsolutePath() + "/" + ID);
+
+        assertThat(rollback.isStaged()).isFalse();
+        assertThat(rollback.info.getRollbackId()).isEqualTo(ID);
+        assertThat(rollback.info.getPackages()).isEmpty();
+        assertThat(rollback.isEnabling()).isTrue();
+    }
+
+    @Test
+    public void createStaged() {
+        Rollback rollback = mRollbackStore.createStagedRollback(ID, 897);
+
+        assertThat(rollback.getBackupDir().getAbsolutePath())
+                .isEqualTo(mFolder.getRoot().getAbsolutePath() + "/" + ID);
+
+        assertThat(rollback.isStaged()).isTrue();
+        assertThat(rollback.getStagedSessionId()).isEqualTo(897);
+
+        assertThat(rollback.info.getRollbackId()).isEqualTo(ID);
+        assertThat(rollback.info.getPackages()).isEmpty();
+        assertThat(rollback.isEnabling()).isTrue();
+    }
+
+    @Test
+    public void saveAndLoadRollback() {
+        Rollback origRb = mRollbackStore.createNonStagedRollback(ID);
+
+        origRb.setRestoreUserDataInProgress(true);
+        origRb.info.getCausePackages().add(new VersionedPackage("com.made.up", 2));
+        origRb.info.getCausePackages().add(new VersionedPackage("com.pack.age", 99));
+        origRb.info.setCommittedSessionId(123456);
+
+        PackageRollbackInfo pkgInfo1 =
+                new PackageRollbackInfo(new VersionedPackage("com.made.up", 18),
+                        new VersionedPackage("com.something.else", 5), new IntArray(),
+                        new ArrayList<>(), false, new IntArray(), new SparseLongArray());
+        pkgInfo1.getPendingBackups().add(8);
+        pkgInfo1.getPendingBackups().add(888);
+        pkgInfo1.getPendingBackups().add(88885);
+        pkgInfo1.getCeSnapshotInodes().put(12, 424);
+        pkgInfo1.getCeSnapshotInodes().put(222772, 10000000000L);
+        pkgInfo1.getCeSnapshotInodes().put(10, -67);
+
+        pkgInfo1.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(4980, 3442322, "seInfo"));
+        pkgInfo1.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(-89, 15, "otherSeInfo"));
+
+        pkgInfo1.getSnapshottedUsers().add(11);
+        pkgInfo1.getSnapshottedUsers().add(1);
+        pkgInfo1.getSnapshottedUsers().add(0);
+
+        PackageRollbackInfo pkgInfo2 = new PackageRollbackInfo(
+                new VersionedPackage("another.package", 2),
+                new VersionedPackage("com.test.ing", 48888), new IntArray(), new ArrayList<>(),
+                false, new IntArray(), new SparseLongArray());
+        pkgInfo2.getPendingBackups().add(57);
+
+        pkgInfo2.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(180, -120, ""));
+
+        origRb.info.getPackages().add(pkgInfo1);
+        origRb.info.getPackages().add(pkgInfo2);
+
+        RollbackStore.saveRollback(origRb);
+
+        List<Rollback> loadedRollbacks = mRollbackStore.loadRollbacks();
+        assertThat(loadedRollbacks).hasSize(1);
+        Rollback loadedRb = loadedRollbacks.get(0);
+
+        assertRollbacksAreEquivalent(loadedRb, origRb);
+    }
+
+    @Test
+    public void loadFromJson() throws Exception {
+        Rollback expectedRb = mRollbackStore.createNonStagedRollback(ID);
+
+        expectedRb.setTimestamp(Instant.parse("2019-10-01T12:29:08.855Z"));
+        expectedRb.setRestoreUserDataInProgress(true);
+        expectedRb.info.getCausePackages().add(new VersionedPackage("hello", 23));
+        expectedRb.info.getCausePackages().add(new VersionedPackage("something", 999));
+        expectedRb.info.setCommittedSessionId(45654465);
+
+        PackageRollbackInfo pkgInfo1 = new PackageRollbackInfo(new VersionedPackage("blah", 55),
+                new VersionedPackage("blah1", 50), new IntArray(), new ArrayList<>(),
+                false, new IntArray(), new SparseLongArray());
+        pkgInfo1.getPendingBackups().add(59);
+        pkgInfo1.getPendingBackups().add(1245);
+        pkgInfo1.getPendingBackups().add(124544);
+        pkgInfo1.getCeSnapshotInodes().put(546546, 345689375);
+        pkgInfo1.getCeSnapshotInodes().put(2222, 81641654445L);
+        pkgInfo1.getCeSnapshotInodes().put(1, -6);
+
+        pkgInfo1.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(498, 32322, "wombles"));
+        pkgInfo1.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(-895, 1, "pingu"));
+
+        pkgInfo1.getSnapshottedUsers().add(498468432);
+        pkgInfo1.getSnapshottedUsers().add(1111);
+        pkgInfo1.getSnapshottedUsers().add(98464);
+
+        PackageRollbackInfo pkgInfo2 = new PackageRollbackInfo(new VersionedPackage("chips", 28),
+                new VersionedPackage("com.chips.test", 48), new IntArray(), new ArrayList<>(),
+                false, new IntArray(), new SparseLongArray());
+        pkgInfo2.getPendingBackups().add(5);
+
+        pkgInfo2.getPendingRestores().add(
+                new PackageRollbackInfo.RestoreInfo(18, -12, ""));
+
+        pkgInfo2.getSnapshottedUsers().add(55);
+        pkgInfo2.getSnapshottedUsers().add(79);
+
+        expectedRb.info.getPackages().add(pkgInfo1);
+        expectedRb.info.getPackages().add(pkgInfo2);
+
+        Rollback parsedRb = RollbackStore.rollbackFromJson(
+                new JSONObject(JSON_ROLLBACK), expectedRb.getBackupDir());
+
+        assertRollbacksAreEquivalent(parsedRb, expectedRb);
+    }
+
+    @Test
+    public void saveAndDelete() {
+        Rollback rollback = mRollbackStore.createNonStagedRollback(ID);
+
+        RollbackStore.saveRollback(rollback);
+
+        File expectedFile = new File(mRollbackDir.getAbsolutePath() + "/rollback.json");
+
+        assertThat(expectedFile.exists()).isTrue();
+
+        RollbackStore.deleteRollback(rollback);
+
+        assertThat(expectedFile.exists()).isFalse();
+    }
+
+    private void assertRollbacksAreEquivalent(Rollback b, Rollback a) {
+        assertThat(b.info.getRollbackId()).isEqualTo(ID);
+
+        assertThat(b.getBackupDir()).isEqualTo(a.getBackupDir());
+
+        assertThat(b.isRestoreUserDataInProgress())
+                .isEqualTo(a.isRestoreUserDataInProgress());
+
+        assertThat(b.getTimestamp()).isEqualTo(a.getTimestamp());
+
+        assertThat(b.isEnabling()).isEqualTo(a.isEnabling());
+        assertThat(b.isAvailable()).isEqualTo(a.isAvailable());
+        assertThat(b.isCommitted()).isEqualTo(a.isCommitted());
+
+        assertThat(b.isStaged()).isEqualTo(a.isStaged());
+
+        assertThat(b.getApexPackageNames())
+                .containsExactlyElementsIn(a.getApexPackageNames());
+
+        assertThat(b.getStagedSessionId()).isEqualTo(a.getStagedSessionId());
+
+        assertThat(b.info.getCommittedSessionId()).isEqualTo(a.info.getCommittedSessionId());
+
+        assertThat(b.info.getCausePackages()).comparingElementsUsing(VER_PKG_CORR)
+                .containsExactlyElementsIn(a.info.getCausePackages());
+
+        assertThat(b.info.getPackages()).hasSize(a.info.getPackages().size());
+
+        for (int i = 0; i < b.info.getPackages().size(); i++) {
+            assertPackageRollbacksAreEquivalent(
+                    b.info.getPackages().get(i), a.info.getPackages().get(i));
+        }
+    }
+
+    private void assertPackageRollbacksAreEquivalent(PackageRollbackInfo b, PackageRollbackInfo a) {
+        assertThat(b.getPackageName()).isEqualTo(a.getPackageName());
+
+        assertThat(b.getVersionRolledBackFrom().getLongVersionCode())
+                .isEqualTo(a.getVersionRolledBackFrom().getLongVersionCode());
+        assertThat(b.getVersionRolledBackFrom().getPackageName())
+                .isEqualTo(a.getVersionRolledBackFrom().getPackageName());
+
+        assertThat(b.getVersionRolledBackTo().getLongVersionCode())
+                .isEqualTo(a.getVersionRolledBackTo().getLongVersionCode());
+        assertThat(b.getVersionRolledBackTo().getPackageName())
+                .isEqualTo(a.getVersionRolledBackTo().getPackageName());
+
+        assertThat(b.getPendingBackups().toArray()).isEqualTo(a.getPendingBackups().toArray());
+
+        assertThat(b.getPendingRestores()).comparingElementsUsing(RESTORE_INFO_CORR)
+                .containsExactlyElementsIn(a.getPendingRestores());
+
+        assertThat(b.isApex()).isEqualTo(a.isApex());
+
+        assertThat(b.getSnapshottedUsers().toArray()).isEqualTo(a.getSnapshottedUsers().toArray());
+
+        assertThat(b.getCeSnapshotInodes().toString())
+                .isEqualTo(a.getCeSnapshotInodes().toString());
+    }
+
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
old mode 100644
new mode 100755
index 2de8d05..e80c629
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3864,7 +3864,9 @@
         mService.simulatePackageDistractionBroadcast(
                 PackageManager.RESTRICTION_HIDE_NOTIFICATIONS, new String[] {"a", "b"});
         ArgumentCaptor<List<NotificationRecord>> captorHide = ArgumentCaptor.forClass(List.class);
-        verify(mListeners, times(2)).notifyHiddenLocked(captorHide.capture());
+
+        // should be called only once.
+        verify(mListeners, times(1)).notifyHiddenLocked(captorHide.capture());
         assertEquals(2, captorHide.getValue().size());
         assertEquals("a", captorHide.getValue().get(0).sbn.getPackageName());
         assertEquals("b", captorHide.getValue().get(1).sbn.getPackageName());
@@ -3873,7 +3875,9 @@
         mService.simulatePackageDistractionBroadcast(
                 PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, new String[] {"a", "b"});
         ArgumentCaptor<List<NotificationRecord>> captorUnhide = ArgumentCaptor.forClass(List.class);
-        verify(mListeners, times(2)).notifyUnhiddenLocked(captorUnhide.capture());
+
+        // should be called only once.
+        verify(mListeners, times(1)).notifyUnhiddenLocked(captorUnhide.capture());
         assertEquals(2, captorUnhide.getValue().size());
         assertEquals("a", captorUnhide.getValue().get(0).sbn.getPackageName());
         assertEquals("b", captorUnhide.getValue().get(1).sbn.getPackageName());
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 59d0735..34eb3f1 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -97,6 +97,8 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
 import java.util.Arrays;
@@ -159,7 +161,7 @@
     int mUsageSource;
 
     /** Manages the standby state of apps. */
-    AppStandbyController mAppStandby;
+    AppStandbyInternal mAppStandby;
 
     /** Manages app time limit observers */
     AppTimeLimitController mAppTimeLimit;
@@ -208,7 +210,9 @@
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mHandler = new H(BackgroundThread.get().getLooper());
 
-        mAppStandby = new AppStandbyController(getContext(), BackgroundThread.get().getLooper());
+        mAppStandby = AppStandbyInternal.newAppStandbyController(
+                UsageStatsService.class.getClassLoader(), getContext(),
+                BackgroundThread.get().getLooper());
 
         mAppTimeLimit = new AppTimeLimitController(
                 new AppTimeLimitController.TimeLimitCallbackListener() {
@@ -1010,7 +1014,7 @@
                         pw.println("Flushed stats to disk");
                         return;
                     } else if ("is-app-standby-enabled".equals(arg)) {
-                        pw.println(mAppStandby.mAppIdleEnabled);
+                        pw.println(mAppStandby.isAppIdleEnabled());
                         return;
                     } else if ("apptimelimit".equals(arg)) {
                         if (i + 1 >= args.length) {
diff --git a/telephony/java/android/telephony/CellBroadcastService.java b/telephony/java/android/telephony/CellBroadcastService.java
new file mode 100644
index 0000000..d5e447e
--- /dev/null
+++ b/telephony/java/android/telephony/CellBroadcastService.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.CallSuper;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * A service which exposes the cell broadcast handling module to the system.
+ * <p>
+ * To extend this class, you must declare the service in your manifest file to require the
+ * {@link android.Manifest.permission#BIND_CELL_BROADCAST_SERVICE} permission and include an intent
+ * filter with the {@link #CELL_BROADCAST_SERVICE_INTERFACE}.
+ * Implementations of this service should run in the phone process and with its UID.
+ * <p>
+ * For example:
+ * <pre>{@code
+ * <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ *       android:sharedUserId="android.uid.phone">
+ *   <service android:name=".MyCellBroadcastService"
+ *         android:label="@string/service_name"
+ *         android:process="com.android.phone"
+ *         android:exported="true"
+ *         android:permission="android.permission.BIND_CELL_BROADCAST_SERVICE">
+ *     <intent-filter>
+ *           <action android:name="android.telephony.CellBroadcastService" />
+ *     </intent-filter>
+ *   </service>
+ * </manifest>
+ * }</pre>
+ * @hide
+ */
+@SystemApi
+public abstract class CellBroadcastService extends Service {
+
+    public static final String CELL_BROADCAST_SERVICE_INTERFACE =
+            "android.telephony.CellBroadcastService";
+
+    private final ICellBroadcastService.Stub mStubWrapper;
+
+    public CellBroadcastService() {
+        mStubWrapper = new ICellBroadcastServiceWrapper();
+    }
+
+    /**
+     * Handle a GSM cell broadcast SMS message forwarded from the system.
+     * @param slotIndex the index of the slot which received the message
+     * @param message the SMS PDU
+     */
+    public abstract void onGsmCellBroadcastSms(int slotIndex, byte[] message);
+
+    /**
+     * Handle a CDMA cell broadcast SMS message forwarded from the system.
+     * @param slotIndex the index of the slot which received the message
+     * @param message the SMS PDU
+     */
+    public abstract void onCdmaCellBroadcastSms(int slotIndex, byte[] message);
+
+    /**
+     * If overriding this method, call through to the super method for any unknown actions.
+     * {@inheritDoc}
+     */
+    @Override
+    @CallSuper
+    public IBinder onBind(Intent intent) {
+        return mStubWrapper;
+    }
+
+    /**
+     * A wrapper around ICellBroadcastService that forwards calls to implementations of
+     * {@link CellBroadcastService}.
+     * @hide
+     */
+    public class ICellBroadcastServiceWrapper extends ICellBroadcastService.Stub {
+        /**
+         * Handle a GSM cell broadcast SMS.
+         * @param slotIndex the index of the slot which received the broadcast
+         * @param message the SMS message PDU
+         */
+        @Override
+        public void handleGsmCellBroadcastSms(int slotIndex, byte[] message) {
+            CellBroadcastService.this.onGsmCellBroadcastSms(slotIndex, message);
+        }
+
+        /**
+         * Handle a CDMA cell broadcast SMS.
+         * @param slotIndex the index of the slot which received the broadcast
+         * @param message the SMS message PDU
+         */
+        @Override
+        public void handleCdmaCellBroadcastSms(int slotIndex, byte[] message) {
+            CellBroadcastService.this.onCdmaCellBroadcastSms(slotIndex, message);
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/ICellBroadcastService.aidl b/telephony/java/android/telephony/ICellBroadcastService.aidl
new file mode 100644
index 0000000..eff64a2
--- /dev/null
+++ b/telephony/java/android/telephony/ICellBroadcastService.aidl
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+/**
+ * Service bound to by the system to allow custom handling of cell broadcast messages.
+ * <p>
+ * @see android.telephony.CellBroadcastService
+ * @hide
+ */
+interface ICellBroadcastService {
+
+    /** @see android.telephony.CellBroadcastService#onGsmCellBroadcastSms */
+    oneway void handleGsmCellBroadcastSms(int slotId, in byte[] message);
+
+    /** @see android.telephony.CellBroadcastService#onCdmaCellBroadcastSms */
+    oneway void handleCdmaCellBroadcastSms(int slotId, in byte[] message);
+}
diff --git a/telephony/java/android/telephony/IFinancialSmsCallback.aidl b/telephony/java/android/telephony/IFinancialSmsCallback.aidl
deleted file mode 100644
index aa88615..0000000
--- a/telephony/java/android/telephony/IFinancialSmsCallback.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-** Copyright 2019, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-package android.telephony;
-
-import android.app.PendingIntent;
-import android.database.CursorWindow;
-import android.net.Uri;
-import android.os.Bundle;
-import com.android.internal.telephony.SmsRawData;
-
-/** Interface for returning back the financial sms messages asynchrously.
- *  @hide
- */
-interface IFinancialSmsCallback {
-    /**
-     * Return sms messages back to calling financial app.
-     *
-     * @param messages the sms messages returned for cinancial app.
-     */
-    oneway void onGetSmsMessagesForFinancialApp(in CursorWindow messages);
-}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index c2028f9..1801cae 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -878,6 +878,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) {
         // default implementation empty
     }
@@ -889,6 +890,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber) {
         // default implementation empty
     }
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 71fcf23..f4330fa 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -33,6 +33,7 @@
 import android.database.CursorWindow;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.BaseBundle;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -2080,7 +2081,9 @@
         }
     }
 
-    /** callback for providing asynchronous sms messages for financial app. */
+    /**
+     * callback for providing asynchronous sms messages for financial app.
+     */
     public abstract static class FinancialSmsCallback {
         /**
          * Callback to send sms messages back to financial app asynchronously.
@@ -2106,24 +2109,14 @@
      * @param params the parameters to filter SMS messages returned.
      * @param executor the executor on which callback will be invoked.
      * @param callback a callback to receive CursorWindow with SMS messages.
+     *
      */
     @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS)
     public void getSmsMessagesForFinancialApp(
             Bundle params,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull FinancialSmsCallback callback) {
-        try {
-            ISms iccSms = getISmsServiceOrThrow();
-            iccSms.getSmsMessagesForFinancialApp(
-                    getSubscriptionId(), ActivityThread.currentPackageName(), params,
-                    new IFinancialSmsCallback.Stub() {
-                        public void onGetSmsMessagesForFinancialApp(CursorWindow msgs) {
-                            Binder.withCleanCallingIdentity(() -> executor.execute(
-                                    () -> callback.onFinancialSmsMessages(msgs)));
-                        }});
-        } catch (RemoteException ex) {
-            ex.rethrowFromSystemServer();
-        }
+        // This API is not functional and thus removed to avoid future confusion.
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 7441c26..f3a335d 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -19,7 +19,6 @@
 import android.app.PendingIntent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.telephony.IFinancialSmsCallback;
 import com.android.internal.telephony.SmsRawData;
 
 /**
@@ -570,17 +569,6 @@
             int subId, String callingPkg, String prefixes, in PendingIntent intent);
 
     /**
-     * Get sms inbox messages for the calling financial app.
-     *
-     * @param subId the SIM id.
-     * @param callingPkg the package name of the calling app.
-     * @param params parameters to filter the sms messages.
-     * @param callback the callback interface to deliver the result.
-     */
-    void getSmsMessagesForFinancialApp(
-        int subId, String callingPkg, in Bundle params, in IFinancialSmsCallback callback);
-
-    /**
      * Check if the destination is a possible premium short code.
      *
      * @param destAddress the destination address to test for possible short code
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
index aa1f94f..2096325 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -19,7 +19,6 @@
 import android.app.PendingIntent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.telephony.IFinancialSmsCallback;
 
 import java.util.List;
 
@@ -198,12 +197,6 @@
     }
 
     @Override
-    public void getSmsMessagesForFinancialApp(
-            int subId, String callingPkg, Bundle params, IFinancialSmsCallback callback) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public int checkSmsShortCodeDestination(
             int subid, String callingApk, String destAddress, String countryIso) {
         throw new UnsupportedOperationException();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index 6eea118..c65c45f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -461,7 +461,11 @@
         }
     }
 
-    static final class GeoFencingTriggerMessage {
+    /**
+     * Part of a GSM SMS cell broadcast message which may trigger geo-fencing logic.
+     * @hide
+     */
+    public static final class GeoFencingTriggerMessage {
         /**
          * Indicate the list of active alerts share their warning area coordinates which means the
          * broadcast area is the union of the broadcast areas of the active alerts in this list.
@@ -476,6 +480,11 @@
             this.cbIdentifiers = cbIdentifiers;
         }
 
+        /**
+         * Whether the trigger message indicates that the broadcast areas are shared between all
+         * active alerts.
+         * @return true if broadcast areas are to be shared
+         */
         boolean shouldShareBroadcastArea() {
             return type == TYPE_ACTIVE_ALERT_SHARE_WAC;
         }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
index 6bbff4b..cbe5211 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
@@ -74,22 +74,22 @@
     /**
      * Length of SMS-CB header
      */
-    static final int PDU_HEADER_LENGTH = 6;
+    public static final int PDU_HEADER_LENGTH = 6;
 
     /**
      * GSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1
      */
-    static final int FORMAT_GSM = 1;
+    public static final int FORMAT_GSM = 1;
 
     /**
      * UMTS pdu format, as defined in 3gpp TS 23.041, section 9.4.2
      */
-    static final int FORMAT_UMTS = 2;
+    public static final int FORMAT_UMTS = 2;
 
     /**
-     * GSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1.3
+     * ETWS pdu format, as defined in 3gpp TS 23.041, section 9.4.1.3
      */
-    static final int FORMAT_ETWS_PRIMARY = 3;
+    public static final int FORMAT_ETWS_PRIMARY = 3;
 
     /**
      * Message type value as defined in 3gpp TS 25.324, section 11.1.
@@ -230,43 +230,43 @@
     }
 
     @UnsupportedAppUsage
-    int getGeographicalScope() {
+    public int getGeographicalScope() {
         return mGeographicalScope;
     }
 
     @UnsupportedAppUsage
-    int getSerialNumber() {
+    public int getSerialNumber() {
         return mSerialNumber;
     }
 
     @UnsupportedAppUsage
-    int getServiceCategory() {
+    public int getServiceCategory() {
         return mMessageIdentifier;
     }
 
-    int getDataCodingScheme() {
+    public int getDataCodingScheme() {
         return mDataCodingScheme;
     }
 
-    DataCodingScheme getDataCodingSchemeStructedData() {
+    public DataCodingScheme getDataCodingSchemeStructedData() {
         return mDataCodingSchemeStructedData;
     }
 
     @UnsupportedAppUsage
-    int getPageIndex() {
+    public int getPageIndex() {
         return mPageIndex;
     }
 
     @UnsupportedAppUsage
-    int getNumberOfPages() {
+    public int getNumberOfPages() {
         return mNrOfPages;
     }
 
-    SmsCbEtwsInfo getEtwsInfo() {
+    public SmsCbEtwsInfo getEtwsInfo() {
         return mEtwsInfo;
     }
 
-    SmsCbCmasInfo getCmasInfo() {
+    public SmsCbCmasInfo getCmasInfo() {
         return mCmasInfo;
     }
 
@@ -274,7 +274,7 @@
      * Return whether this broadcast is an emergency (PWS) message type.
      * @return true if this message is emergency type; false otherwise
      */
-    boolean isEmergencyMessage() {
+    public boolean isEmergencyMessage() {
         return mMessageIdentifier >= SmsCbConstants.MESSAGE_ID_PWS_FIRST_IDENTIFIER
                 && mMessageIdentifier <= SmsCbConstants.MESSAGE_ID_PWS_LAST_IDENTIFIER;
     }
@@ -292,7 +292,7 @@
      * Return whether this broadcast is an ETWS primary notification.
      * @return true if this message is an ETWS primary notification; false otherwise
      */
-    boolean isEtwsPrimaryNotification() {
+    public boolean isEtwsPrimaryNotification() {
         return mFormat == FORMAT_ETWS_PRIMARY;
     }
 
@@ -300,7 +300,7 @@
      * Return whether this broadcast is in UMTS format.
      * @return true if this message is in UMTS format; false otherwise
      */
-    boolean isUmtsFormat() {
+    public boolean isUmtsFormat() {
         return mFormat == FORMAT_UMTS;
     }
 
diff --git a/tests/Codegen/runTest.sh b/tests/Codegen/runTest.sh
index 614cbb7..01522735 100755
--- a/tests/Codegen/runTest.sh
+++ b/tests/Codegen/runTest.sh
@@ -13,6 +13,7 @@
     header_and_eval m -j16 codegen_cli && \
         header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java && \
         header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java && \
+        header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java && \
         cd $ANDROID_BUILD_TOP &&
         header_and_eval mmma -j16 frameworks/base/tests/Codegen && \
         header_and_eval adb install -r -t $ANDROID_PRODUCT_OUT/testcases/CodegenTests/arm64/CodegenTests.apk && \
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
new file mode 100644
index 0000000..2d41257
--- /dev/null
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.codegentest;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.util.AnnotationValidations;
+import com.android.internal.util.DataClass;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Additional test for various parcelling corner-cases.
+ */
+@DataClass(
+        genBuilder = true,
+        genAidl = false,
+        genToString = true)
+public class ParcelAllTheThingsDataClass implements Parcelable {
+
+    @NonNull String[] mStringArray = null;
+    @NonNull int[] mIntArray = null;
+    @NonNull List<String> mStringList = null;
+
+    @NonNull Map<String, SampleWithCustomBuilder> mMap = null;
+    @NonNull Map<String, String> mStringMap = null;
+
+    @NonNull SparseArray<SampleWithCustomBuilder> mSparseArray = null;
+    @NonNull SparseIntArray mSparseIntArray = null;
+
+
+
+    // Code below generated by codegen v1.0.4.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+
+
+    @DataClass.Generated.Member
+    /* package-private */ ParcelAllTheThingsDataClass(
+            @NonNull String[] stringArray,
+            @NonNull int[] intArray,
+            @NonNull List<String> stringList,
+            @NonNull Map<String,SampleWithCustomBuilder> map,
+            @NonNull Map<String,String> stringMap,
+            @NonNull SparseArray<SampleWithCustomBuilder> sparseArray,
+            @NonNull SparseIntArray sparseIntArray) {
+        this.mStringArray = stringArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringArray);
+        this.mIntArray = intArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mIntArray);
+        this.mStringList = stringList;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringList);
+        this.mMap = map;
+        AnnotationValidations.validate(
+                NonNull.class, null, mMap);
+        this.mStringMap = stringMap;
+        AnnotationValidations.validate(
+                NonNull.class, null, mStringMap);
+        this.mSparseArray = sparseArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mSparseArray);
+        this.mSparseIntArray = sparseIntArray;
+        AnnotationValidations.validate(
+                NonNull.class, null, mSparseIntArray);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull String[] getStringArray() {
+        return mStringArray;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull int[] getIntArray() {
+        return mIntArray;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull List<String> getStringList() {
+        return mStringList;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull Map<String,SampleWithCustomBuilder> getMap() {
+        return mMap;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull Map<String,String> getStringMap() {
+        return mStringMap;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull SparseArray<SampleWithCustomBuilder> getSparseArray() {
+        return mSparseArray;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull SparseIntArray getSparseIntArray() {
+        return mSparseIntArray;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "ParcelAllTheThingsDataClass { " +
+                "stringArray = " + java.util.Arrays.toString(mStringArray) + ", " +
+                "intArray = " + java.util.Arrays.toString(mIntArray) + ", " +
+                "stringList = " + mStringList + ", " +
+                "map = " + mMap + ", " +
+                "stringMap = " + mStringMap + ", " +
+                "sparseArray = " + mSparseArray + ", " +
+                "sparseIntArray = " + mSparseIntArray +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeStringArray(mStringArray);
+        dest.writeIntArray(mIntArray);
+        dest.writeStringList(mStringList);
+        dest.writeMap(mMap);
+        dest.writeMap(mStringMap);
+        dest.writeSparseArray(mSparseArray);
+        dest.writeSparseIntArray(mSparseIntArray);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<ParcelAllTheThingsDataClass> CREATOR
+            = new Parcelable.Creator<ParcelAllTheThingsDataClass>() {
+        @Override
+        public ParcelAllTheThingsDataClass[] newArray(int size) {
+            return new ParcelAllTheThingsDataClass[size];
+        }
+
+        @Override
+        @SuppressWarnings({"unchecked", "RedundantCast"})
+        public ParcelAllTheThingsDataClass createFromParcel(Parcel in) {
+            // You can override field unparcelling by defining methods like:
+            // static FieldType unparcelFieldName(Parcel in) { ... }
+
+            String[] stringArray = in.createStringArray();
+            int[] intArray = in.createIntArray();
+            List<String> stringList = new java.util.ArrayList<>();
+            in.readStringList(stringList);
+            Map<String,SampleWithCustomBuilder> map = new java.util.LinkedHashMap<>();
+            in.readMap(map, SampleWithCustomBuilder.class.getClassLoader());
+            Map<String,String> stringMap = new java.util.LinkedHashMap<>();
+            in.readMap(stringMap, String.class.getClassLoader());
+            SparseArray<SampleWithCustomBuilder> sparseArray = (SparseArray) in.readSparseArray(SampleWithCustomBuilder.class.getClassLoader());
+            SparseIntArray sparseIntArray = (SparseIntArray) in.readSparseIntArray();
+            return new ParcelAllTheThingsDataClass(
+                    stringArray,
+                    intArray,
+                    stringList,
+                    map,
+                    stringMap,
+                    sparseArray,
+                    sparseIntArray);
+        }
+    };
+
+    /**
+     * A builder for {@link ParcelAllTheThingsDataClass}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static class Builder {
+
+        private @NonNull String[] mStringArray;
+        private @NonNull int[] mIntArray;
+        private @NonNull List<String> mStringList;
+        private @NonNull Map<String,SampleWithCustomBuilder> mMap;
+        private @NonNull Map<String,String> mStringMap;
+        private @NonNull SparseArray<SampleWithCustomBuilder> mSparseArray;
+        private @NonNull SparseIntArray mSparseIntArray;
+
+        private long mBuilderFieldsSet = 0L;
+
+        public Builder() {
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setStringArray(@NonNull String... value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mStringArray = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setIntArray(@NonNull int... value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mIntArray = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setStringList(@NonNull List<String> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mStringList = value;
+            return this;
+        }
+
+        /** @see #setStringList */
+        @DataClass.Generated.Member
+        public @NonNull Builder addStringList(String value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mStringList == null) setStringList(new java.util.ArrayList<>());
+            mStringList.add(value);
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setMap(@NonNull Map<String,SampleWithCustomBuilder> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mMap = value;
+            return this;
+        }
+
+        /** @see #setMap */
+        @DataClass.Generated.Member
+        public @NonNull Builder addMap(String key, SampleWithCustomBuilder value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mMap == null) setMap(new java.util.LinkedHashMap());
+            mMap.put(key, value);
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setStringMap(@NonNull Map<String,String> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10;
+            mStringMap = value;
+            return this;
+        }
+
+        /** @see #setStringMap */
+        @DataClass.Generated.Member
+        public @NonNull Builder addStringMap(String key, String value) {
+            // You can refine this method's name by providing item's singular name, e.g.:
+            // @DataClass.PluralOf("item")) mItems = ...
+
+            if (mStringMap == null) setStringMap(new java.util.LinkedHashMap());
+            mStringMap.put(key, value);
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setSparseArray(@NonNull SparseArray<SampleWithCustomBuilder> value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x20;
+            mSparseArray = value;
+            return this;
+        }
+
+        @DataClass.Generated.Member
+        public @NonNull Builder setSparseIntArray(@NonNull SparseIntArray value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x40;
+            mSparseIntArray = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public ParcelAllTheThingsDataClass build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x80; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x1) == 0) {
+                mStringArray = null;
+            }
+            if ((mBuilderFieldsSet & 0x2) == 0) {
+                mIntArray = null;
+            }
+            if ((mBuilderFieldsSet & 0x4) == 0) {
+                mStringList = null;
+            }
+            if ((mBuilderFieldsSet & 0x8) == 0) {
+                mMap = null;
+            }
+            if ((mBuilderFieldsSet & 0x10) == 0) {
+                mStringMap = null;
+            }
+            if ((mBuilderFieldsSet & 0x20) == 0) {
+                mSparseArray = null;
+            }
+            if ((mBuilderFieldsSet & 0x40) == 0) {
+                mSparseIntArray = null;
+            }
+            ParcelAllTheThingsDataClass o = new ParcelAllTheThingsDataClass(
+                    mStringArray,
+                    mIntArray,
+                    mStringList,
+                    mMap,
+                    mStringMap,
+                    mSparseArray,
+                    mSparseIntArray);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x80) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1570139502128L,
+            codegenVersion = "1.0.4",
+            sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java",
+            inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
+    @Deprecated
+    private void __metadata() {}
+
+}
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index 66c7d06..0631f7d 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -342,7 +342,7 @@
 
 
 
-    // Code below generated by codegen v1.0.3.
+    // Code below generated by codegen v1.0.4.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -1798,8 +1798,8 @@
     }
 
     @DataClass.Generated(
-            time = 1569956013899L,
-            codegenVersion = "1.0.3",
+            time = 1570139500112L,
+            codegenVersion = "1.0.4",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java",
             inputSignatures = "public static final  java.lang.String STATE_NAME_UNDEFINED\npublic static final  java.lang.String STATE_NAME_ON\npublic static final  java.lang.String STATE_NAME_OFF\npublic static final  int STATE_UNDEFINED\npublic static final  int STATE_ON\npublic static final  int STATE_OFF\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate  int mNum\nprivate  int mNum2\nprivate  int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient  android.net.LinkAddress[] mLinkAddresses6\ntransient  int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static  java.lang.String defaultName4()\nprivate  int[] lazyInitTmpStorage()\npublic  android.net.LinkAddress[] getLinkAddresses4()\nprivate  boolean patternEquals(java.util.regex.Pattern)\nprivate  int patternHashCode()\nprivate  void onConstructed()\npublic  void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java b/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
index 6636207..c7a7735 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
@@ -25,9 +25,14 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThat;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import android.net.LinkAddress;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -36,6 +41,9 @@
 
 import java.util.Arrays;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -209,6 +217,32 @@
         newBuilder().setDayOfWeek(42).build();
     }
 
+    @Test
+    public void testDataStructures_parcelCorrectly() {
+        SampleWithCustomBuilder otherParcelable = new SampleWithCustomBuilder.Builder().setDelay(3, SECONDS).build();
+
+        ParcelAllTheThingsDataClass instance = new ParcelAllTheThingsDataClass.Builder()
+                .setIntArray(40, 41)
+                .addMap("foo", otherParcelable)
+                .setSparseArray(new SparseArray<SampleWithCustomBuilder>() {{
+                    put(45, otherParcelable);
+                }})
+                .setSparseIntArray(new SparseIntArray() {{
+                    put(48, 49);
+                }})
+                .addStringMap("foo2", "fooValue")
+                .setStringArray("foo", "bar")
+                .addStringList("foo")
+                .build();
+
+        ParcelAllTheThingsDataClass unparceledInstance =
+                parcelAndUnparcel(instance, ParcelAllTheThingsDataClass.CREATOR);
+
+        // SparseArray and friends don't implement equals
+        // so just compare string representations instead
+        assertEquals(instance.toString(), unparceledInstance.toString());
+    }
+
     private static <T extends Parcelable> T parcelAndUnparcel(
             T original, Parcelable.Creator<T> creator) {
         Parcel p = Parcel.obtain();
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index c6bc8de..0f8c663 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -17,14 +17,16 @@
 package com.android.codegentest;
 
 import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.SystemClock;
 
 import com.android.internal.util.DataClass;
 
 import java.util.concurrent.TimeUnit;
 
-@DataClass(genBuilder = true)
-public class SampleWithCustomBuilder {
+@DataClass(genBuilder = true, genAidl = false, genToString = true)
+public class SampleWithCustomBuilder implements Parcelable {
 
     long delayAmount = 0;
     @NonNull
@@ -73,8 +75,17 @@
     }
 
 
+    private static TimeUnit unparcelDelayUnit(Parcel p) {
+        return TimeUnit.values()[p.readInt()];
+    }
 
-    // Code below generated by codegen v1.0.3.
+    private void parcelDelayUnit(Parcel p, int flags) {
+        p.writeInt(delayUnit.ordinal());
+    }
+
+
+
+    // Code below generated by codegen v1.0.4.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -112,6 +123,58 @@
         return creationTimestamp;
     }
 
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "SampleWithCustomBuilder { " +
+                "delayAmount = " + delayAmount + ", " +
+                "delayUnit = " + delayUnit + ", " +
+                "creationTimestamp = " + creationTimestamp +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeLong(delayAmount);
+        parcelDelayUnit(dest, flags);
+        dest.writeLong(creationTimestamp);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<SampleWithCustomBuilder> CREATOR
+            = new Parcelable.Creator<SampleWithCustomBuilder>() {
+        @Override
+        public SampleWithCustomBuilder[] newArray(int size) {
+            return new SampleWithCustomBuilder[size];
+        }
+
+        @Override
+        @SuppressWarnings({"unchecked", "RedundantCast"})
+        public SampleWithCustomBuilder createFromParcel(Parcel in) {
+            // You can override field unparcelling by defining methods like:
+            // static FieldType unparcelFieldName(Parcel in) { ... }
+
+            long _delayAmount = in.readLong();
+            TimeUnit _delayUnit = unparcelDelayUnit(in);
+            long _creationTimestamp = in.readLong();
+            return new SampleWithCustomBuilder(
+                    _delayAmount,
+                    _delayUnit,
+                    _creationTimestamp);
+        }
+    };
+
     /**
      * A builder for {@link SampleWithCustomBuilder}
      */
@@ -176,10 +239,10 @@
     }
 
     @DataClass.Generated(
-            time = 1569956014908L,
-            codegenVersion = "1.0.3",
+            time = 1570139501160L,
+            codegenVersion = "1.0.4",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java",
-            inputSignatures = "  long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n  long creationTimestamp\nclass SampleWithCustomBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true)\nabstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic  com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
+            inputSignatures = "  long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n  long creationTimestamp\nprivate static  java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate  void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic  com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
     private void __metadata() {}
 
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index 914e475..8653405 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -341,7 +341,7 @@
             }
         }
 
-        if (Type.contains("Map<")) {
+        if (FieldClass.endsWith("Map") && FieldInnerType != null) {
             generateBuilderMethod(
                     name = adderName,
                     defVisibility = visibility,
@@ -533,7 +533,7 @@
                             } else if (Type !in PRIMITIVE_TYPES + "String" + "Bundle" &&
                                     (!isArray || FieldInnerType !in PRIMITIVE_TYPES + "String") &&
                                     ParcelMethodsSuffix != "Parcelable") {
-                                !"($Type) "
+                                !"($FieldClass) "
                             }
                         }
 
@@ -541,12 +541,15 @@
                         when {
                             ParcelMethodsSuffix == "Parcelable" ->
                                 methodArgs += "$FieldClass.class.getClassLoader()"
+                            ParcelMethodsSuffix == "SparseArray" ->
+                                methodArgs += "$FieldInnerClass.class.getClassLoader()"
                             ParcelMethodsSuffix == "TypedObject" ->
                                 methodArgs += "$FieldClass.CREATOR"
                             ParcelMethodsSuffix == "TypedArray" ->
                                 methodArgs += "$FieldInnerClass.CREATOR"
+                            ParcelMethodsSuffix == "Map" ->
+                                methodArgs += "${fieldTypeGenegicArgs[1].substringBefore("<")}.class.getClassLoader()"
                             ParcelMethodsSuffix.startsWith("Parcelable")
-                                    || FieldClass == "Map"
                                     || (isList || isArray)
                                     && FieldInnerType !in PRIMITIVE_TYPES + "String" ->
                                 methodArgs += "$FieldInnerClass.class.getClassLoader()"
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 1e3973e..1cc7ef3 100644
--- a/tools/codegen/src/com/android/codegen/SharedConstants.kt
+++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt
@@ -1,7 +1,7 @@
 package com.android.codegen
 
 const val CODEGEN_NAME = "codegen"
-const val CODEGEN_VERSION = "1.0.3"
+const val CODEGEN_VERSION = "1.0.4"
 
 const val CANONICAL_BUILDER_CLASS = "Builder"
 const val BASE_BUILDER_CLASS = "BaseBuilder"